├── .flake8
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── dependabot.yml
├── pull_request_template.md
└── workflows
│ ├── docs-check.yml
│ └── tests-coverage.yml
├── .gitignore
├── .isort.cfg
├── .pre-commit-config.yaml
├── .readthedocs.yml
├── LICENSE
├── README.md
├── doc
├── Makefile
├── conf.py
├── configs.rst
├── definitions_and_units.rst
├── dev_notes.rst
├── eDisGo_UML.graphml
├── equipment.rst
├── features_in_detail.rst
├── genindex.rst
├── images
│ ├── cosphi-sign-convention_generation.png
│ ├── cosphi-sign-convention_load.png
│ ├── edisgo_logo.png
│ └── grid_expansion_measures.png
├── index.rst
├── make.bat
├── quickstart.rst
├── units_table.csv
├── usage_details.rst
├── whatsnew.rst
└── whatsnew
│ ├── v0-0-10.rst
│ ├── v0-0-2.rst
│ ├── v0-0-3.rst
│ ├── v0-0-5.rst
│ ├── v0-0-6.rst
│ ├── v0-0-7.rst
│ ├── v0-0-8.rst
│ ├── v0-0-9.rst
│ ├── v0-1-0.rst
│ ├── v0-1-1.rst
│ ├── v0-2-0.rst
│ ├── v0-2-1.rst
│ └── v0-3-0.rst
├── eDisGo_env.yml
├── eDisGo_env_dev.yml
├── edisgo
├── __init__.py
├── config
│ ├── config_db_tables_default.cfg
│ ├── config_grid_default.cfg
│ ├── config_grid_expansion_default.cfg
│ ├── config_opf_julia_default.cfg
│ ├── config_system.cfg
│ └── config_timeseries_default.cfg
├── edisgo.py
├── equipment
│ ├── equipment-parameters_LV_cables.csv
│ ├── equipment-parameters_LV_transformers.csv
│ ├── equipment-parameters_MV_cables.csv
│ ├── equipment-parameters_MV_overhead_lines.csv
│ ├── equipment-parameters_MV_transformers.csv
│ └── equipment_data.meta
├── flex_opt
│ ├── __init__.py
│ ├── battery_storage_operation.py
│ ├── charging_strategies.py
│ ├── check_tech_constraints.py
│ ├── costs.py
│ ├── exceptions.py
│ ├── heat_pump_operation.py
│ ├── q_control.py
│ ├── reinforce_grid.py
│ └── reinforce_measures.py
├── io
│ ├── __init__.py
│ ├── db.py
│ ├── ding0_import.py
│ ├── dsm_import.py
│ ├── electromobility_import.py
│ ├── generators_import.py
│ ├── heat_pump_import.py
│ ├── powermodels_io.py
│ ├── pypsa_io.py
│ ├── storage_import.py
│ └── timeseries_import.py
├── network
│ ├── __init__.py
│ ├── components.py
│ ├── dsm.py
│ ├── electromobility.py
│ ├── grids.py
│ ├── heat.py
│ ├── overlying_grid.py
│ ├── results.py
│ ├── timeseries.py
│ └── topology.py
├── opf
│ ├── __init__.py
│ ├── eDisGo_OPF.jl
│ │ ├── Main.jl
│ │ ├── Manifest.toml
│ │ ├── Project.toml
│ │ └── src
│ │ │ ├── core
│ │ │ ├── base.jl
│ │ │ ├── constraint.jl
│ │ │ ├── constraint_template.jl
│ │ │ ├── data.jl
│ │ │ ├── objective.jl
│ │ │ ├── solution.jl
│ │ │ ├── types.jl
│ │ │ └── variables.jl
│ │ │ ├── eDisGo_OPF.jl
│ │ │ ├── form
│ │ │ └── bf.jl
│ │ │ ├── io
│ │ │ ├── common.jl
│ │ │ └── json.jl
│ │ │ └── prob
│ │ │ └── opf_bf.jl
│ ├── opf_solutions
│ │ └── __init__.py
│ ├── powermodels_opf.py
│ ├── results
│ │ ├── __init__.py
│ │ └── opf_result_class.py
│ └── timeseries_reduction.py
└── tools
│ ├── __init__.py
│ ├── config.py
│ ├── geo.py
│ ├── geopandas_helper.py
│ ├── logger.py
│ ├── networkx_helper.py
│ ├── plots.py
│ ├── powermodels_io.py
│ ├── preprocess_pypsa_opf_structure.py
│ ├── pseudo_coordinates.py
│ ├── spatial_complexity_reduction.py
│ ├── temporal_complexity_reduction.py
│ └── tools.py
├── examples
├── data
│ ├── vg250.cpg
│ ├── vg250.dbf
│ ├── vg250.prj
│ ├── vg250.shp
│ └── vg250.shx
├── edisgo_simple_example.ipynb
├── electromobility_example.ipynb
└── plot_example.ipynb
├── rtd_requirements.txt
├── setup.py
└── tests
├── conftest.py
├── data
├── ding0_test_network_1
│ ├── buses.csv
│ ├── ding0_test_network_1.md
│ ├── generators.csv
│ ├── lines.csv
│ ├── loads.csv
│ ├── network.csv
│ ├── storage_units.csv
│ ├── switches.csv
│ ├── transformers.csv
│ └── transformers_hvmv.csv
├── ding0_test_network_2
│ ├── Ding0_20210416184606.meta
│ ├── buses.csv
│ ├── generators.csv
│ ├── lines.csv
│ ├── loads.csv
│ ├── network.csv
│ ├── switches.csv
│ ├── transformers.csv
│ └── transformers_hvmv.csv
├── ding0_test_network_3
│ ├── buses.csv
│ ├── generators.csv
│ ├── lines.csv
│ ├── loads.csv
│ ├── network.csv
│ ├── switches.csv
│ ├── transformers.csv
│ └── transformers_hvmv.csv
├── simbev_example_scenario
│ ├── 5334032
│ │ ├── bev_luxury_00000_110kWh_SR_Mitte_events.csv
│ │ ├── bev_luxury_00001_110kWh_SR_Mitte_events.csv
│ │ ├── bev_luxury_00002_110kWh_SR_Mitte_events.csv
│ │ ├── bev_medium_00000_90kWh_SR_Mitte_events.csv
│ │ ├── bev_medium_00001_90kWh_SR_Mitte_events.csv
│ │ ├── bev_medium_00002_90kWh_SR_Mitte_events.csv
│ │ ├── bev_mini_00000_60kWh_SR_Mitte_events.csv
│ │ ├── bev_mini_00001_60kWh_SR_Mitte_events.csv
│ │ ├── bev_mini_00002_60kWh_SR_Mitte_events.csv
│ │ ├── phev_luxury_00000_30kWh_SR_Mitte_events.csv
│ │ ├── phev_medium_00000_20kWh_SR_Mitte_events.csv
│ │ └── phev_mini_00003_14kWh_SR_Mitte_events.csv
│ └── metadata_simbev_run.json
└── tracbev_example_scenario
│ ├── output_home_05334032.gpkg
│ ├── output_hpc_05334032.gpkg
│ ├── output_public_05334032.gpkg
│ └── output_work_05334032.gpkg
├── flex_opt
├── test_battery_storage_operation.py
├── test_charging_strategy.py
├── test_check_tech_constraints.py
├── test_costs.py
├── test_heat_pump_operation.py
├── test_q_control.py
├── test_reinforce_grid.py
└── test_reinforce_measures.py
├── io
├── test_ding0_import.py
├── test_dsm_import.py
├── test_electromobility_import.py
├── test_generators_import.py
├── test_heat_pump_import.py
├── test_powermodels_io.py
├── test_pypsa_io.py
├── test_storage_import.py
└── test_timeseries_import.py
├── network
├── test_components.py
├── test_dsm.py
├── test_electromobility.py
├── test_grids.py
├── test_heat.py
├── test_overlying_grid.py
├── test_results.py
├── test_timeseries.py
└── test_topology.py
├── opf
└── test_powermodels_opf.py
├── test_edisgo.py
├── test_examples.py
└── tools
├── test_geopandas_helper.py
├── test_logger.py
├── test_plots.py
├── test_pseudo_coordinates.py
├── test_spatial_complexity_reduction.py
├── test_temporal_complexity_reduction.py
└── test_tools.py
/.flake8:
--------------------------------------------------------------------------------
1 | [flake8]
2 | extend-exclude = docs
3 | max-line-length = 88
4 | extend-ignore = E203
5 | count = true
6 | statistics = true
7 | show-source = true
8 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: "[BUG]"
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Additional context**
27 | Add any other context about the problem here.
28 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: "[FEATURE]"
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "pip"
4 | directory: "/"
5 | schedule:
6 | interval: "daily"
7 | reviewers:
8 | - "joda9"
9 | labels:
10 | - "dependencies"
11 | rebase-strategy: "auto"
12 | ignore:
13 | - dependency-name: "pandas"
14 | - dependency-name: "plotly"
15 | - dependency-name: "pypsa"
16 | - dependency-name: "scikit-learn"
17 | - dependency-name: "sqlalchemy"
18 | - package-ecosystem: "github-actions"
19 | directory: "/"
20 | schedule:
21 | interval: "daily"
22 | reviewers:
23 | - "joda9"
24 | labels:
25 | - "dependencies"
26 | rebase-strategy: "auto"
27 | ignore:
28 | - dependency-name: "pandas"
29 | - dependency-name: "plotly"
30 | - dependency-name: "pypsa"
31 | - dependency-name: "scikit-learn"
32 | - dependency-name: "sqlalchemy"
33 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | # Description
2 |
3 | Please include a summary of the change and which issue is fixed.
4 |
5 | Fixes # (issue)
6 |
7 | ## Type of change
8 |
9 | Please delete options that are not relevant.
10 |
11 | - [ ] Bug fix (non-breaking change which fixes an issue)
12 | - [ ] New feature (non-breaking change which adds functionality)
13 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
14 |
15 | # Checklist:
16 |
17 | - [ ] New and adjusted code is formatted using the `pre-commit` hooks
18 | - [ ] New and adjusted code includes type hinting now
19 | - [ ] I have commented my code, particularly in hard-to-understand areas
20 | - [ ] I have made corresponding changes to the documentation
21 | - [ ] I have added tests that prove my fix is effective or that my feature works
22 | - [ ] New and existing unit tests pass locally with my changes
23 | - [ ] The Read the Docs documentation is compiling correctly
24 | - [ ] If new packages are needed, I added them the [setup.py](https://github.com/openego/eDisGo/blob/dev/setup.py), and if needed the [rtd_requirements.txt](https://github.com/openego/eDisGo/blob/dev/rtd_requirements.txt), the [eDisGo_env.yml](https://github.com/openego/eDisGo/blob/dev/eDisGo_env.yml) and the [eDisGo_env_dev.yml](https://github.com/openego/eDisGo/blob/dev/eDisGo_env_dev.yml).
25 | - [ ] I have added new features to the corresponding [whatsnew](https://github.com/openego/eDisGo/tree/dev/doc/whatsnew) file
26 |
--------------------------------------------------------------------------------
/.github/workflows/docs-check.yml:
--------------------------------------------------------------------------------
1 | name: "Docs link check"
2 | on: [push]
3 |
4 | jobs:
5 | build:
6 | runs-on: ubuntu-latest
7 | steps:
8 | - uses: actions/checkout@v4
9 | - name: Install dependencies
10 | run: |
11 | sudo apt install pandoc
12 | python -m pip install --upgrade pip
13 | pip install -r rtd_requirements.txt
14 | - name: Check doc links
15 | run: |
16 | sphinx-build . -b linkcheck -d _build/doctrees _build/html
17 | working-directory: ./doc
18 |
--------------------------------------------------------------------------------
/.github/workflows/tests-coverage.yml:
--------------------------------------------------------------------------------
1 | # Tests with pytest the package and monitors the covarage and sends it to coveralls.io
2 | # Coverage is only send to coveralls.io when no pytest tests fail
3 | name: "Tests & Coverage"
4 |
5 | on: [push]
6 |
7 | # Cancel jobs on new push
8 | concurrency:
9 | group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
10 | cancel-in-progress: true
11 |
12 | jobs:
13 | build:
14 | name: "${{ matrix.name-suffix }} at py${{ matrix.python-version }} on ${{ matrix.os }}"
15 | runs-on: ${{ matrix.os }}
16 |
17 | strategy:
18 | fail-fast: false
19 | matrix:
20 | include:
21 | - name-suffix: "coverage"
22 | os: ubuntu-latest
23 | python-version: 3.9
24 | - name-suffix: "basic"
25 | os: ubuntu-latest
26 | python-version: "3.10"
27 | - name-suffix: "basic"
28 | os: ubuntu-latest
29 | python-version: 3.11
30 | - name-suffix: "basic"
31 | os: windows-latest
32 | python-version: 3.9
33 |
34 | steps:
35 | - name: Checkout repo
36 | uses: actions/checkout@v4
37 |
38 | - name: Set up Python
39 | uses: actions/setup-python@v5
40 | with:
41 | python-version: ${{ matrix.python-version }}
42 |
43 | - name: Set up julia
44 | if: runner.os == 'Linux'
45 | uses: julia-actions/setup-julia@v2
46 | with:
47 | version: "1.6"
48 |
49 | - name: Install packages (Linux)
50 | if: runner.os == 'Linux'
51 | run: |
52 | pip install --upgrade pip wheel setuptools
53 | pip install -e "."
54 |
55 | - name: Install packages (Windows)
56 | if: runner.os == 'Windows'
57 | uses: conda-incubator/setup-miniconda@v3
58 | with:
59 | miniconda-version: "latest"
60 | activate-environment: edisgo_env
61 | environment-file: eDisGo_env_dev.yml
62 | python-version: ${{ matrix.python-version }}
63 |
64 | - name: Run tests Linux
65 | if: runner.os == 'Linux' && matrix.name-suffix != 'coverage'
66 | run: |
67 | python -m pip install pytest pytest-notebook
68 | python -m pytest --runslow --runonlinux --disable-warnings --color=yes -v
69 | env:
70 | TOEP_TOKEN_KH: ${{ secrets.TOEP_TOKEN_KH }}
71 |
72 | - name: Run tests Windows
73 | if: runner.os == 'Windows'
74 | run: |
75 | python -m pip install pytest pytest-notebook
76 | python -m pytest --runslow --disable-warnings --color=yes -v
77 | env:
78 | TOEP_TOKEN_KH: ${{ secrets.TOEP_TOKEN_KH }}
79 |
80 | - name: Run tests, coverage and send to coveralls
81 | if: runner.os == 'Linux' && matrix.python-version == 3.9 && matrix.name-suffix == 'coverage'
82 | run: |
83 | pip install pytest pytest-notebook coveralls
84 | coverage run --source=edisgo -m pytest --runslow --runonlinux --disable-warnings --color=yes -v
85 | coveralls
86 | env:
87 | TOEP_TOKEN_KH: ${{ secrets.TOEP_TOKEN_KH }}
88 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
89 | COVERALLS_SERVICE_NAME: github
90 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # exclude project files
2 | .idea/
3 |
4 |
5 | # exclude certain types of files
6 | *.doctree
7 | *.txt
8 | *.html
9 | *.js
10 | *.inv
11 | *.pyc
12 | *.ttf
13 | *.woff
14 | *.css
15 | *.pkl
16 | *.ipynb_checkpoints
17 |
18 | # exclude locally built docs
19 | doc/_html
20 |
21 | # exclude egg-info
22 | eDisGo.egg-info/
23 |
24 | # exclude .json files in opf
25 | /edisgo/opf/opf_solutions/*.json
26 | /edisgo/opf/eDisGo_OPF.jl/.vscode
27 | .vscode/settings.json
28 |
29 | *TOEP_TOKEN.*
30 |
--------------------------------------------------------------------------------
/.isort.cfg:
--------------------------------------------------------------------------------
1 | [settings]
2 | profile = black
3 | multi_line_output = 3
4 | lines_between_types = 1
5 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/pre-commit/pre-commit-hooks
3 | rev: v5.0.0
4 | hooks:
5 | - id: check-yaml
6 | - id: end-of-file-fixer
7 | - id: trailing-whitespace
8 | - repo: https://github.com/psf/black
9 | rev: 25.1.0
10 | hooks:
11 | - id: black
12 | - repo: https://github.com/pycqa/flake8
13 | rev: 7.1.1
14 | hooks:
15 | - id: flake8
16 | - repo: https://github.com/pycqa/isort
17 | rev: 6.0.0
18 | hooks:
19 | - id: isort
20 | name: isort (python)
21 | - repo: https://github.com/asottile/pyupgrade
22 | rev: v3.19.1
23 | hooks:
24 | - id: pyupgrade
25 | #- repo: https://github.com/pycqa/pylint
26 | # rev: pylint-2.6.0
27 | # hooks:
28 | # - id: pylint
29 | - repo: https://github.com/kynan/nbstripout
30 | rev: 0.8.1
31 | hooks:
32 | - id: nbstripout
33 |
--------------------------------------------------------------------------------
/.readthedocs.yml:
--------------------------------------------------------------------------------
1 | # .readthedocs.yml
2 | # Read the Docs configuration file
3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
4 |
5 | # Required
6 | version: 2
7 |
8 | # Build documentation in the docs/ directory with Sphinx
9 | sphinx:
10 | configuration: doc/conf.py
11 |
12 | # Build documentation with MkDocs
13 | #mkdocs:
14 | # configuration: mkdocs.yml
15 |
16 | # Optionally build your docs in additional formats such as PDF and ePub
17 | formats: all
18 |
19 | # Optionally set the version of Python and requirements required to build your docs
20 | python:
21 | install:
22 | - requirements: rtd_requirements.txt
23 |
24 | # Set the version of Python
25 | build:
26 | os: ubuntu-22.04
27 | tools:
28 | python: "3.9"
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | # Overview
5 |
6 | [](https://coveralls.io/github/openego/eDisGo?branch=dev)
7 | [](https://github.com/openego/eDisGo/actions/workflows/tests-coverage.yml)
8 |
9 |
10 | # eDisGo
11 |
12 | The python package eDisGo serves as a toolbox to evaluate flexibility measures
13 | as an economic alternative to conventional grid expansion in
14 | medium and low voltage grids.
15 | See [documentation](https://edisgo.readthedocs.io/en/dev/) for further information.
16 |
17 |
18 | # LICENSE
19 |
20 | Copyright (C) 2017 Reiner Lemoine Institut gGmbH
21 |
22 | This program is free software: you can redistribute it and/or modify it under
23 | the terms of the GNU Affero General Public License as published by the Free
24 | Software Foundation, either version 3 of the License, or (at your option) any
25 | later version.
26 |
27 | This program is distributed in the hope that it will be useful, but WITHOUT
28 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
29 | FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
30 | details.
31 |
32 | You should have received a copy of the GNU General Public License along with
33 | this program. If not, see https://www.gnu.org/licenses/.
34 |
--------------------------------------------------------------------------------
/doc/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = .
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/doc/configs.rst:
--------------------------------------------------------------------------------
1 | .. _default_configs:
2 |
3 | Default configuration data
4 | ============================
5 |
6 | Following you find the default configuration files.
7 |
8 | .. _config_db:
9 |
10 | config_db_tables
11 | -------------------
12 |
13 | The config file ``config_db_tables.cfg`` holds data about which database connection
14 | to use from your saved database connections and which dataprocessing version.
15 |
16 | .. include:: ../edisgo/config/config_db_tables_default.cfg
17 | :literal:
18 |
19 | .. _config_grid_expansion:
20 |
21 | config_grid_expansion
22 | ----------------------
23 |
24 | The config file ``config_grid_expansion.cfg`` holds data mainly needed to determine
25 | grid expansion needs and costs - these are standard equipment to use in grid expansion and
26 | its costs, as well as allowed voltage deviations and line load factors.
27 |
28 | .. include:: ../edisgo/config/config_grid_expansion_default.cfg
29 | :literal:
30 |
31 | .. _config_timeseries:
32 |
33 | config_timeseries
34 | ----------------------
35 |
36 | The config file ``config_timeseries.cfg`` holds data to define the two worst-case
37 | scenarions heavy load flow ('load case') and reverse power flow ('feed-in case')
38 | used in conventional grid expansion planning, power factors and modes (inductive
39 | or capacitative) to generate reactive power time series, as well as configurations
40 | of the demandlib in case load time series are generated using the oemof demandlib.
41 |
42 | .. include:: ../edisgo/config/config_timeseries_default.cfg
43 | :literal:
44 |
45 | .. _config_grid:
46 |
47 | config_grid
48 | ----------------------
49 |
50 | The config file ``config_grid.cfg`` holds data to specify parameters used when
51 | connecting new generators to the grid and where to position disconnecting points.
52 |
53 | .. include:: ../edisgo/config/config_grid_default.cfg
54 | :literal:
55 |
--------------------------------------------------------------------------------
/doc/definitions_and_units.rst:
--------------------------------------------------------------------------------
1 | Definition and units
2 | ====================
3 |
4 | Sign Convention
5 | ---------------
6 |
7 | Generators and Loads in an AC power system can behave either like an inductor or a capacitor. Mathematically,
8 | this has two different sign conventions, either from the generator perspective or from the load perspective.
9 | This is defined by the direction of power flow from the component.
10 |
11 | Both sign conventions are used in eDisGo depending upon the components being defined, similar to pypsa.
12 |
13 | Generator Sign Convention
14 | ^^^^^^^^^^^^^^^^^^^^^^^^^
15 | .. _generator_sign_convention_label:
16 | .. figure:: images/cosphi-sign-convention_generation.png
17 |
18 | Generator sign convention in detail
19 |
20 | While defining time series for :class:`~.grid.components.Generator`, :class:`~.grid.components.GeneratorFluctuating`,
21 | and :class:`~.grid.components.Storage`, the generator sign convention is used.
22 |
23 |
24 | Load Sign Convention
25 | ^^^^^^^^^^^^^^^^^^^^
26 | .. _load_sign_convention_label:
27 | .. figure:: images/cosphi-sign-convention_load.png
28 |
29 | Load sign convention in detail
30 |
31 | The time series for :class:`~.grid.components.Load` is defined using the load sign convention.
32 |
33 |
34 | Reactive Power Sign Convention
35 | ------------------------------
36 |
37 | Generators and Loads in an AC power system can behave either like an inductor or a capacitor. Mathematically,
38 | this has two different sign conventions, either from the generator perspective or from the load perspective.
39 |
40 | Both sign conventions are used in eDisGo, similar to pypsa. While defining time series for
41 | :class:`~.grid.components.Generator`, :class:`~.grid.components.GeneratorFluctuating`, and
42 | :class:`~.grid.components.Storage`, the generator sign convention is used. This means that when
43 | the reactive power (Q) is positive, the component shows capacitive behaviour and when the reactive power (Q) is
44 | negative, the component shows inductive behaviour.
45 |
46 | The time series for :class:`~.grid.components.Load` is defined using the load sign convention. This means
47 | that when the reactive power (Q) is positive, the component shows inductive behaviour and when the
48 | reactive power (Q) is negative, the component shows capacitive behaviour. This is the direct opposite of the
49 | generator sign convention.
50 |
51 |
52 | Units
53 | -----
54 | .. csv-table:: List of variables and units
55 | :file: units_table.csv
56 | :delim: ;
57 | :header-rows: 1
58 | :widths: 5, 1, 1, 5
59 | :stub-columns: 0
60 |
--------------------------------------------------------------------------------
/doc/dev_notes.rst:
--------------------------------------------------------------------------------
1 | .. _dev-notes:
2 |
3 | Notes to developers
4 | ===================
5 |
6 | Installation
7 | ------------
8 |
9 | Clone the repository from `GitHub `_ and change into
10 | the eDisGo directory:
11 |
12 | .. code-block:: bash
13 |
14 | cd eDisGo
15 |
16 |
17 | Installation using Linux
18 | ~~~~~~~~~~~~~~~~~~~~~~~~
19 |
20 | To set up a source installation using linux simply use a virtual environment and install
21 | the source code with pip. Make sure to use python3.9 or higher. **After** setting up your virtual environment and activating it run the
22 | following commands within your eDisGo directory:
23 |
24 | .. code-block:: bash
25 |
26 | python -m pip install -e .[dev] # install eDisGo from source
27 | pre-commit install # install pre-commit hooks
28 |
29 |
30 | Installation using Windows
31 | ~~~~~~~~~~~~~~~~~~~~~~~~~~
32 |
33 | For Windows users we recommend using Anaconda and to install the geo stack
34 | using the conda-forge channel prior to installing eDisGo. You may use the provided
35 | `eDisGo_env_dev.yml file `_
36 | to do so. Create the virtual environment with:
37 |
38 | .. code-block:: bash
39 |
40 | conda env create -f path/to/eDisGo_env_dev.yml # install eDisGo from source
41 |
42 | Activate the newly created environment and install the pre-commit hooks with:
43 |
44 | .. code-block:: bash
45 |
46 | conda activate eDisGo_env_dev
47 | pre-commit install # install pre-commit hooks
48 |
49 | This will install eDisGo with all its dependencies.
50 |
51 | Installation using MacOS
52 | ~~~~~~~~~~~~~~~~~~~~~~~~~
53 |
54 | We don't have any experience with our package on MacOS yet! If you try eDisGo on MacOS
55 | we would be happy if you let us know about your experience!
56 |
57 |
58 | Code standards
59 | --------------
60 |
61 | * **pre-commit hooks**: Make sure to use the provided pre-commit hooks
62 | * **pytest**: Make sure that all pytest tests are passing and add tests for every new code base
63 | * **Documentation of `@property` functions**: Put documentation of getter and setter
64 | both in Docstring of getter, see
65 | `on Stackoverflow `_
66 | * Order of public/private/protected methods, property decorators, etc. in a class: TBD
67 |
68 |
69 | Documentation
70 | -------------
71 |
72 | You can build the docs locally as follows (executed from top-level eDisGo directory):
73 |
74 | .. code-block:: bash
75 |
76 | sphinx-build -E -a -b html ./doc/
77 |
78 | To manually check if external links in the documentation work, you can run the following command (internal links are not checked by this):
79 |
80 | .. code-block:: bash
81 |
82 | sphinx-build ./doc/ -b linkcheck -d _build/doctrees _build/html
83 |
84 | Internal links can be checked adding -n option when building the documentation. This will
85 | also raise warnings for type hinting, so it is a bit confusing, but can still be helpful.
86 |
87 | .. code-block:: bash
88 |
89 | sphinx-build -n -E -a -b html ./doc/
90 |
--------------------------------------------------------------------------------
/doc/equipment.rst:
--------------------------------------------------------------------------------
1 | .. _equipment:
2 |
3 | Equipment data
4 | =================
5 |
6 | The following tables hold all data of cables, lines and transformers used.
7 |
8 | .. _lv_cables_table:
9 |
10 | .. csv-table:: LV cables
11 | :file: ../edisgo/equipment/equipment-parameters_LV_cables.csv
12 | :delim: ,
13 | :header-rows: 2
14 | :widths: 3, 1, 1, 1, 1, 1
15 | :stub-columns: 0
16 |
17 | .. _mv_cables_table:
18 |
19 | .. csv-table:: MV cables
20 | :file: ../edisgo/equipment/equipment-parameters_MV_cables.csv
21 | :delim: ,
22 | :header-rows: 2
23 | :widths: 4, 1, 1, 1, 1, 1
24 | :stub-columns: 0
25 |
26 | .. _mv_lines_table:
27 |
28 | .. csv-table:: MV overhead lines
29 | :file: ../edisgo/equipment/equipment-parameters_MV_overhead_lines.csv
30 | :delim: ,
31 | :header-rows: 2
32 | :widths: 4, 1, 1, 1, 1, 1
33 | :stub-columns: 0
34 |
35 | .. _lv_transformers_table:
36 |
37 | .. csv-table:: LV transformers
38 | :file: ../edisgo/equipment/equipment-parameters_LV_transformers.csv
39 | :delim: ,
40 | :header-rows: 2
41 | :widths: 5, 1, 1, 1
42 | :stub-columns: 0
43 |
44 | .. _mv_transformers_table:
45 |
46 | .. csv-table:: MV transformers
47 | :file: ../edisgo/equipment/equipment-parameters_MV_transformers.csv
48 | :delim: ,
49 | :header-rows: 2
50 | :widths: 5, 1
51 | :stub-columns: 0
52 |
--------------------------------------------------------------------------------
/doc/genindex.rst:
--------------------------------------------------------------------------------
1 | Index
2 | ==================
3 |
4 | :ref:`genindex`
5 |
--------------------------------------------------------------------------------
/doc/images/cosphi-sign-convention_generation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/doc/images/cosphi-sign-convention_generation.png
--------------------------------------------------------------------------------
/doc/images/cosphi-sign-convention_load.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/doc/images/cosphi-sign-convention_load.png
--------------------------------------------------------------------------------
/doc/images/edisgo_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/doc/images/edisgo_logo.png
--------------------------------------------------------------------------------
/doc/images/grid_expansion_measures.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/doc/images/grid_expansion_measures.png
--------------------------------------------------------------------------------
/doc/index.rst:
--------------------------------------------------------------------------------
1 | Welcome to the documentation of eDisGo!
2 | ========================================
3 |
4 | .. figure:: images/edisgo_logo.png
5 | :align: right
6 | :scale: 70%
7 |
8 | The python package eDisGo serves as a toolbox to evaluate flexibility measures
9 | as an economic alternative to conventional grid expansion in
10 | medium and low voltage grids.
11 |
12 | The toolbox currently includes:
13 |
14 | * Data import from external data sources
15 |
16 | * `ding0 `_ tool for synthetic medium and low
17 | voltage grid topologies for the whole of Germany
18 | * `OpenEnergy DataBase (oedb) `_ for
19 | feed-in time series of fluctuating renewables and scenarios for future
20 | power plant park of Germany
21 | * `demandlib `_ for electrical load time series
22 | * `SimBEV `_ and
23 | `TracBEV `_ for charging demand data of electric
24 | vehicles, respectively potential charging point locations
25 |
26 | * Static, non-linear power flow analysis using `PyPSA `_ for
27 | grid issue identification
28 | * Automatic grid reinforcement methodology solving overloading and voltage issues
29 | to determine grid expansion needs and costs based on measures most commonly
30 | taken by German distribution grid operators
31 | * Implementation of different charging strategies of electric vehicles
32 | * Multiperiod optimal power flow based on julia package PowerModels.jl optimizing
33 | storage positioning and/or operation (Currently not maintained)
34 | as well as generator dispatch with regard to minimizing grid expansion costs
35 | * Temporal complexity reduction
36 | * Heuristic for grid-supportive generator curtailment (Currently not maintained)
37 | * Heuristic grid-supportive battery storage integration (Currently not maintained)
38 |
39 | Currently, a method to optimize the flexibility that can be provided by electric
40 | vehicles through controlled charging is being implemented.
41 | Prospectively, demand side management and reactive power management will
42 | be included.
43 |
44 | See :ref:`quickstart` for the first steps.
45 | A deeper guide is provided in :ref:`usage-details`.
46 | Methodologies are explained in detail in :ref:`features-in-detail`.
47 | For those of you who want to contribute see :ref:`dev-notes` and the
48 | API reference.
49 |
50 | eDisGo was initially developed in the
51 | `open_eGo `_ research project as part of
52 | a grid planning tool that can be used to determine the optimal grid and storage
53 | expansion of the German power grid over all voltage levels and has been used in
54 | two publications of the project:
55 |
56 | * `Integrated Techno-Economic Power System Planning of Transmission and Distribution Grids `_
57 | * `Final report of the open_eGo project (in German) `_
58 |
59 | Contents
60 | ==================
61 |
62 | .. toctree::
63 | :maxdepth: 2
64 |
65 | quickstart
66 | usage_details
67 | features_in_detail
68 | dev_notes
69 | definitions_and_units
70 | configs
71 | equipment
72 | whatsnew
73 | genindex
74 |
--------------------------------------------------------------------------------
/doc/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=.
11 | set BUILDDIR=_build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/doc/units_table.csv:
--------------------------------------------------------------------------------
1 | Variable;Symbol;Unit;Comment
2 | Current;I;kA;
3 | Length;l;km;
4 | Active Power;P;MW;
5 | Reactive Power;Q;MVar;
6 | Apparent Power;S;MVA;
7 | Resistance;R;Ohm or Ohm/km;Ohm/km applies to lines
8 | Reactance;X;Ohm or Ohm/km;Ohm/km applies to lines
9 | Voltage;V;kV;
10 | Inductance;L;mH/km;
11 | Capacitance;C;µF/km;
12 | Costs;-;kEUR;
13 |
--------------------------------------------------------------------------------
/doc/whatsnew.rst:
--------------------------------------------------------------------------------
1 | What's New
2 | ~~~~~~~~~~
3 |
4 | Changelog for each release.
5 |
6 | .. contents::
7 | :depth: 1
8 | :local:
9 | :backlinks: top
10 |
11 | .. include:: whatsnew/v0-2-1.rst
12 | .. include:: whatsnew/v0-2-0.rst
13 | .. include:: whatsnew/v0-1-1.rst
14 | .. include:: whatsnew/v0-1-0.rst
15 | .. include:: whatsnew/v0-0-10.rst
16 | .. include:: whatsnew/v0-0-9.rst
17 | .. include:: whatsnew/v0-0-8.rst
18 | .. include:: whatsnew/v0-0-7.rst
19 | .. include:: whatsnew/v0-0-6.rst
20 | .. include:: whatsnew/v0-0-5.rst
21 | .. include:: whatsnew/v0-0-3.rst
22 | .. include:: whatsnew/v0-0-2.rst
23 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0-0-10.rst:
--------------------------------------------------------------------------------
1 | Release v0.0.10
2 | ================
3 |
4 | Release date: October 18, 2019
5 |
6 | Changes
7 | -------
8 | * Updated to networkx 2.0
9 | * Changed data of transformers `#240 `_
10 | * Proper session handling and readonly usage (PR `#160 `_)
11 |
12 | Bug fixes
13 | ----------
14 | * Corrected calculation of current from pypsa power flow results (PR `#153 `_).
15 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0-0-2.rst:
--------------------------------------------------------------------------------
1 | Release v0.0.2
2 | ==============
3 |
4 | Release date: March 15 2018
5 |
6 | The code was heavily revised. Now, eDisGo provides the top-level API class
7 | :class:`~.grid.network.EDisGo` for user interaction. See below for details and
8 | other small changes.
9 |
10 | Changes
11 | -------
12 |
13 | * Switch disconnector/ disconnecting points are now relocated by eDisGo
14 | `#99 `_. Before,
15 | locations determined by Ding0 were used. Relocation is conducted according to
16 | minimal load differences in both parts of the ring.
17 | * Switch disconnectors are always located in LV stations
18 | `#23 `_
19 | * Made all round speed improvements as mentioned in the issues `#43 `_
20 | * The structure of eDisGo and its input data has been extensively revised in order to
21 | make it more consistent and easier to use. We introduced a top-level API class called :class:`~.grid.network.EDisGo` through which all user
22 | input and measures are now handled. The EDisGo class thereby replaces the former Scenario class and parts of the Network class.
23 | See :ref:`edisgo-mwe` for a quick overview of how to use the EDisGo class or :ref:`usage-details` for a more comprehensive
24 | introduction to the edisgo structure and usage.
25 | * We introduce a CLI script to use basic functionality of eDisGo including
26 | parallelization. CLI uses higher level functions to run eDisGo. Consult
27 | :mod:`~.tools.edisgo_run` for further details.
28 | `#93 `_.
29 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0-0-3.rst:
--------------------------------------------------------------------------------
1 | Release v0.0.3
2 | ==============
3 |
4 | Release date: July 6 2018
5 |
6 | New features have been included in this release. Major changes being the use of the weather_cell_id and
7 | the inclusion of new methods for distributing the curtailment to be more suitable to network operations.
8 |
9 | Changes
10 | -------
11 |
12 | * As part of the solution to github issues `#86 `_,
13 | `#98 `_, Weather cell information was of importance due to the changes
14 | in the source of data. The table `ego_renewable_feedin_v031` is now used to provide this feedin time series indexed
15 | using the weather cell id's. Changes were made to ego.io and ding0 to correspondingly allow the use of this table
16 | by eDisGo.
17 |
18 | * A new curtailment method have been included based on the voltages at the nodes with `GeneratorFluctuating` objects.
19 | The method is called `curtail_voltage` and its objective is to increase curtailment at locations where voltages
20 | are very high, thereby alleviating over-voltage issues and also reducing the need for network reinforcement.
21 |
22 | * Add parallelization for custon functions
23 | `#130 `_
24 |
25 | * Update `ding0 version to v0.1.6 `_ and include
26 | `data processing v.4.2 data `_
27 |
28 | * Bug Fixes
29 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0-0-5.rst:
--------------------------------------------------------------------------------
1 | Release v0.0.5
2 | ==============
3 |
4 | Release date: July 19, 2018
5 |
6 | Most important changes in this release are some major bug fixes, a differentiation of line load factors and
7 | allowed voltage deviations for load and feed-in case in the grid reinforcement and a possibility to update
8 | time series in the pypsa representation.
9 |
10 | Changes
11 | -------
12 |
13 | * Switch disconnecters in MV rings will now be installed, even if no LV station
14 | exists in the ring `#136 `_
15 | * Update to new version of ding0
16 | `v0.1.7 `_
17 | * Consider feed-in and load case in grid expansion methodology
18 | * Enable grid expansion on snapshots
19 | * Bug fixes
20 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0-0-6.rst:
--------------------------------------------------------------------------------
1 | Release v0.0.6
2 | ==============
3 |
4 | Release date: September 6, 2018
5 |
6 | This release comes with a bunch of new features such as results output and visualization, speed-up options, a new storage
7 | integration methodology and an option to provide separate allowed voltage deviations for calculation of grid expansion needs.
8 | See list of changes below for more details.
9 |
10 | Changes
11 | -------
12 |
13 | * A methodolgy to integrate storages in the MV grid to reduce grid expansion costs was added that takes a given storage capacity and operation and allocates it to multiple smaller storages.
14 | This methodology is mainly to be used together with the `eTraGo tool `_ where an optimization of the HV and EHV levels is conducted to calculate
15 | optiomal storage size and operation at each HV/MV substation.
16 | * The voltage-based curtailment methodolgy was adapted to take into account allowed voltage deviations and curtail generators with voltages that exceed the allowed voltage deviation
17 | more than generators with voltages that do not exceed the allowed voltage deviation.
18 | * When conducting grid reinforcement it is now possible to apply separate allowed voltage deviations for different voltage levels (`#108 `_).
19 | Furthermore, an additional check was added at the end of the grid expansion methodology if the 10%-criterion was observed.
20 | * To speed up calculations functions to update the pypsa representation of the edisgo graph after generator import, storage integration and time series update, e.g. after curtailment, were added.
21 | * Also as a means to speed up calculations an option to calculate grid expansion costs for the two worst time steps, characterized by highest and lowest residual load at the HV/MV substation,
22 | was added.
23 | * For the newly added storage integration methodology it was necessary to calculate grid expansion costs without changing the topology of the graph in order to identify feeders with
24 | high grid expansion needs. Therefore, the option to conduct grid reinforcement on a copy of the graph was added to the grid expansion function.
25 | * So far loads and generators always provided or consumed inductive reactive power with the specified power factor. It is now possible to specify whether loads and generators should
26 | behave as inductors or capacitors and to provide a concrete reactive power time series(`#131 `_).
27 | * The Results class was extended by outputs for storages, grid losses and active and reactive power at the HV/MV substation (`#138 `_)
28 | as well as by a function to save all results to csv files.
29 | * A plotting function to plot line loading in the MV grid was added.
30 | * Update `ding0 version to v0.1.8 `_ and include
31 | `data processing v0.4.5 data `_
32 | * `Bug fix `_
33 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0-0-7.rst:
--------------------------------------------------------------------------------
1 | Release v0.0.7
2 | ==============
3 |
4 | Release date: October 23, 2018
5 |
6 | This release mainly focuses on new plotting functionalities and making reimporting saved results
7 | to further analyze and visualize them more comfortable.
8 |
9 | Changes
10 | -------
11 |
12 | * new plotting methods in the EDisGo API class (plottings of the MV grid topology showing line loadings,
13 | grid expansion costs, voltages and/or integrated storages and histograms
14 | for voltages and relative line loadings)
15 | * new classes EDisGoReimport, NetworkReimport and ResultsReimport to reimport saved results
16 | and enable all analysis and plotting functionalities offered by the original classes
17 | * bug fixes
18 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0-0-8.rst:
--------------------------------------------------------------------------------
1 | Release v0.0.8
2 | ==============
3 |
4 | Release date: October 29, 2018
5 |
6 | Changes
7 | -------
8 | * added tolerance for curtailment targets slightly higher than generator availability to allow small
9 | rounding errors
10 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0-0-9.rst:
--------------------------------------------------------------------------------
1 | Release v0.0.9
2 | ==============
3 |
4 | Release date: December 3, 2018
5 |
6 | Changes
7 | -------
8 |
9 | * bug fix in determining voltage deviation in LV stations and LV grid
10 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0-1-0.rst:
--------------------------------------------------------------------------------
1 | Release v0.1.0
2 | ================
3 |
4 | Release date: July 26, 2021
5 |
6 | This release comes with some major refactoring. The internal data structure
7 | of the network topologies was changed from a networkx graph structure to
8 | a pandas dataframe structure based on the
9 | `PyPSA `_ data structure. This comes
10 | along with major API changes.
11 | Not all functionality of the previous eDisGo release 0.0.10 is yet refactored
12 | (e.g. the heuristics for grid supportive storage integration and generator
13 | curtailment), but we are working on it and the upcoming releases will
14 | have the full functionality again.
15 |
16 | Besides the refactoring we added extensive tests along with automatic testing
17 | with GitHub Actions and coveralls tool to track test coverage.
18 |
19 | Further, from now on python 3.6 is not supported anymore. Supported python
20 | versions are 3.7, 3.8 and 3.9.
21 |
22 | Changes
23 | -------
24 |
25 | * Major refactoring `#159 `_
26 | * Added support for Python 3.7, 3.8 and 3.9 `#181 `_
27 | * Added GitHub Actions for testing and coverage `#180 `_
28 | * Adapted to new ding0 release `#184 `_ - loads and generators in the same building are now connected to the same bus instead of separate buses and loads and generators in aggregated load areas are connected via a MV/LV station instead of directly to the HV/MV station)
29 | * Added charging points as new components along with a methodology to integrate them into the grid
30 | * Added multiperiod optimal power flow based on julia package PowerModels.jl optimizing storage positioning and/or operation as well as generator dispatch with regard to minimizing grid expansion costs
31 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0-1-1.rst:
--------------------------------------------------------------------------------
1 | Release v0.1.1
2 | ================
3 |
4 | Release date: July 22, 2022
5 |
6 | This release comes with some minor additions and bug fixes.
7 |
8 | Changes
9 | -------
10 |
11 | * Added a pull request and issue template
12 | * Fix readthecods API doc
13 | * Consider parallel lines in calculation of x, r and s_nom
14 | * Bug fix calculation of x and r of new lines
15 | * Bug fix of getting a list of all weather cells within grid district
16 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0-2-0.rst:
--------------------------------------------------------------------------------
1 | Release v0.2.0
2 | ================
3 |
4 | Release date: November 10, 2022
5 |
6 | Changes
7 | -------
8 |
9 | * added pre-commit hooks (flake8, black, isort, pyupgrade) `#229 `_
10 | * added issue and pull request templates `#220 `_
11 | * added Windows installation yml and documentation
12 | * added automatic testing for Windows `#317 `_
13 | * dropped support for python 3.7
14 | * added functionality to set up different loggers with individual logging levels and where to write output `#295 `_
15 | * added integrity checks of eDisGo object `#231 `_
16 | * added functionality to save to and load from zip archive `#216 `_
17 | * added option to not raise error in case power flow did not converge `#207 `_
18 | * added pyplot `#214 `_
19 | * added functionality to create geopandas dataframes `#224 `_
20 | * added functionality to resample time series `#269 `_
21 | * added tests
22 | * major refactoring of loads and time series
23 |
24 | * restructured time series module to allow more options on how to set component time series `#236 `_
25 | * added charging points to Topology.loads_df to make eDisGo more flexible when further new load types are added
26 | * peak_load in Topology.loads_df is renamed to p_nom `#242 `_
27 | * renamed all occurences of feedin in config files to feed-in
28 | * added simultaneity factors for heat pumps and electric vehicles
29 | * grid reinforcement now considers separate simultaneity factors for dimensioning of LV and MV `#252 `_
30 |
31 | * added interface to electromobility data from tools SimBEV and TracBEV (SimBEV provides data on
32 | standing times, charging demand, etc. per vehicle, whereas TracBEV provides potential charging point locations)
33 | `#174 `_ and
34 | `#191 `_
35 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0-2-1.rst:
--------------------------------------------------------------------------------
1 | Release v0.2.1
2 | ================
3 |
4 | Release date: April 2, 2023
5 |
6 | Changes
7 | -------
8 |
9 | * Added automatic resampling when applying a charging strategy `#332 `_
10 | * Added MV grid ID to logging output `#309 `_
11 | * Added automatic link checking `#297 `_
12 | * Bug fix `#346 `_
13 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0-3-0.rst:
--------------------------------------------------------------------------------
1 | Release v0.3.0
2 | ================
3 |
4 | Release date: ,
5 |
6 | Changes
7 | -------
8 |
9 | * Added functionalities to obtain electromobility, DSM, storage and electricity timeseries data from oedb `#328 `_
10 | * Added functionalities to obtain heat pump data from oedb `#324 `_
11 | * Added functionality to resample and check integrity of flexibility bands `#341 `_
12 | * Added spatial complexity reduction methods `#343 `_
13 | * Added function to sort buses in lines dataframe such that bus0 is always the upstream bus `#335 `_
14 | * Changed to_pypsa function such that pypsa network can be build even though not all components have time series `#335 `_
15 | * Added class holding data from overlying grid, such as curtailment requirements and
16 | conventional generator dispatch `#335 `_
17 | * Added integrity check for very short lines `#335 `_
18 | * Refactoring of check_tech_constraints functions `#290 `_
19 | * Add background map to plots `#346 `_
20 | * Added method to scale timeseries `#353 `_
21 | * Added method to iteratively reinforce a grid in case the power flow analysis does not always converge `#353 `_
22 | * Added method to aggregate LV grid buses to station bus secondary side `#353 `_
23 | * Adapted codebase to work with pandas 2.0 `#373 `_
24 | * Added option to run reinforcement with reduced number of time steps `#379 `_
25 | (adapted in `#395 `_)
26 | * Added optimization method to determine dispatch of flexibilities that lead to minimal network expansion costs `#376 `_
27 | * Added a new reinforcement method that separate lv grids when the overloading is very high `#380 `_
28 | * Move function to assign feeder to Topology class and add methods to the Grid class to get information on the feeders `#360 `_
29 | * Added a storage operation strategy where the storage is charged when PV feed-in is higher than electricity demand of the household and discharged when electricity demand exceeds PV generation `#386 `_
30 | * Added an estimation of the voltage deviation over a cable when selecting a suitable cable to connect a new component `#411 `_
31 | * Added clipping of heat pump electrical power at its maximum value #428
32 |
--------------------------------------------------------------------------------
/eDisGo_env.yml:
--------------------------------------------------------------------------------
1 | name: eDisGo_env
2 | channels:
3 | - conda-forge
4 | - defaults
5 | dependencies:
6 | - python >= 3.9, <= 3.11
7 | - pip
8 | - pandas >= 1.4, < 2.2.0
9 | - conda-forge::fiona
10 | - conda-forge::geopy
11 | - conda-forge::geopandas
12 | - conda-forge::pyproj
13 | - conda-forge::shapely
14 | - conda-forge::rasterio
15 | - conda-forge::geoalchemy2
16 | - conda-forge::pygeos
17 | - conda-forge::contextily
18 | - conda-forge::descartes
19 | - conda-forge::pypsa == 0.26.2
20 | - pip:
21 | - eDisGo
22 |
--------------------------------------------------------------------------------
/eDisGo_env_dev.yml:
--------------------------------------------------------------------------------
1 | name: eDisGo_env_dev
2 | channels:
3 | - conda-forge
4 | - defaults
5 | dependencies:
6 | - python >= 3.9, <= 3.11
7 | - pip
8 | - pandas >= 1.4, < 2.2.0
9 | - conda-forge::fiona
10 | - conda-forge::geopy
11 | - conda-forge::geopandas
12 | - conda-forge::pyproj
13 | - conda-forge::shapely
14 | - conda-forge::rasterio
15 | - conda-forge::geoalchemy2
16 | - conda-forge::pygeos
17 | - conda-forge::contextily
18 | - conda-forge::descartes
19 | - conda-forge::pypsa == 0.26.2
20 | - pip:
21 | - -e .[dev]
22 |
--------------------------------------------------------------------------------
/edisgo/__init__.py:
--------------------------------------------------------------------------------
1 | from edisgo.edisgo import EDisGo # noqa: F401
2 |
--------------------------------------------------------------------------------
/edisgo/config/config_db_tables_default.cfg:
--------------------------------------------------------------------------------
1 | # This file is part of eDisGo, a python package for distribution grid
2 | # analysis and optimization.
3 | #
4 | # It is developed in the project open_eGo: https://openegoproject.wordpress.com
5 | #
6 | # eDisGo lives on github: https://github.com/openego/edisgo/
7 | # The documentation is available on RTD: https://edisgo.readthedocs.io/en/dev/
8 |
9 | [data_source]
10 |
11 | oedb_data_source = versioned
12 |
13 | [model_draft]
14 |
15 | conv_generators_prefix = t_ego_supply_conv_powerplant_
16 | conv_generators_suffix = _mview
17 | re_generators_prefix = t_ego_supply_res_powerplant_
18 | re_generators_suffix = _mview
19 | res_feedin_data = EgoRenewableFeedin
20 | load_data = EgoDemandHvmvDemand
21 | load_areas = EgoDemandLoadarea
22 |
23 | #conv_generators_nep2035 = t_ego_supply_conv_powerplant_nep2035_mview
24 | #conv_generators_ego100 = ego_supply_conv_powerplant_ego100_mview
25 | #re_generators_nep2035 = t_ego_supply_res_powerplant_nep2035_mview
26 | #re_generators_ego100 = t_ego_supply_res_powerplant_ego100_mview
27 |
28 | [versioned]
29 |
30 | conv_generators_prefix = t_ego_dp_conv_powerplant_
31 | conv_generators_suffix = _mview
32 | re_generators_prefix = t_ego_dp_res_powerplant_
33 | re_generators_suffix = _mview
34 | res_feedin_data = EgoRenewableFeedin
35 | load_data = EgoDemandHvmvDemand
36 | load_areas = EgoDemandLoadarea
37 |
38 | version = v0.4.5
39 |
--------------------------------------------------------------------------------
/edisgo/config/config_grid_default.cfg:
--------------------------------------------------------------------------------
1 | # This file is part of eDisGo, a python package for distribution grid
2 | # analysis and optimization.
3 | #
4 | # It is developed in the project open_eGo: https://openegoproject.wordpress.com
5 | #
6 | # eDisGo lives on github: https://github.com/openego/edisgo/
7 | # The documentation is available on RTD: https://edisgo.readthedocs.io/en/dev/
8 |
9 | # Config file to specify parameters used when connecting new generators to the grid and
10 | # where to position disconnecting points.
11 |
12 | [geo]
13 |
14 | # WGS84: 4326
15 | srid = 4326
16 |
17 | [grid_connection]
18 |
19 | # branch_detour_factor:
20 | # normally, lines do not go straight from A to B due to obstacles etc. Therefore, a detour factor is used.
21 | # unit: -
22 | branch_detour_factor = 1.3
23 |
24 | # conn_buffer_radius:
25 | # radius used to find connection targets
26 | # unit: m
27 | conn_buffer_radius = 2000
28 |
29 | # conn_buffer_radius_inc:
30 | # radius which is incrementally added to connect_buffer_radius as long as no target is found
31 | # unit: m
32 | conn_buffer_radius_inc = 1000
33 |
34 | # conn_diff_tolerance:
35 | # threshold which is used to determine if 2 objects are on the same position
36 | # unit: -
37 | conn_diff_tolerance = 0.0001
38 |
39 | # Upper limits for nominal capacity in MW at which generators, loads and storage units are
40 | # integrated into a certain voltage level. The voltage levels have the following meaning:
41 | # voltage level 7 = LV grid
42 | # voltage level 6 = LV side of MV-LV station
43 | # voltage level 5 = MV grid
44 | # voltage level 4 = MV side of HV-MS station
45 | # The upper limit of one voltage level at the same time signifies the lower limit of
46 | # the next higher voltage level, i.e. upper limit of voltage limit 7 is lower limit for
47 | # voltage level 6.
48 | upper_limit_voltage_level_7 = 0.1
49 | upper_limit_voltage_level_6 = 0.2
50 | upper_limit_voltage_level_5 = 5.5
51 | upper_limit_voltage_level_4 = 20.0
52 |
53 | # from VDE-AR-N 4100 (VDE-AR-N 4100) Anwendungsregel: 2019-04, table 3
54 | lv_max_voltage_deviation = 0.03
55 | # from VDE-AR-N 4110 (VDE-AR-N 4110) Anwendungsregel: 2023-09, 5.3.2 Zulässige Spannungsänderung
56 | mv_max_voltage_deviation = 0.02
57 |
58 | [disconnecting_point]
59 |
60 | # Positioning of disconnecting points: Can be position at location of most
61 | # balanced load or generation. Choose load, generation, loadgen
62 | position = load
63 |
--------------------------------------------------------------------------------
/edisgo/config/config_grid_expansion_default.cfg:
--------------------------------------------------------------------------------
1 | # This file is part of eDisGo, a python package for distribution grid
2 | # analysis and optimization.
3 | #
4 | # It is developed in the project open_eGo: https://openegoproject.wordpress.com
5 | #
6 | # eDisGo lives on github: https://github.com/openego/edisgo/
7 | # The documentation is available on RTD: https://edisgo.readthedocs.io/en/dev/
8 |
9 | [grid_expansion_standard_equipment]
10 |
11 | # standard equipment
12 | # ==================
13 | # Standard equipment for grid expansion measures. Source: Rehtanz et. al.: "Verteilnetzstudie für das Land Baden-Württemberg", 2017.
14 | hv_mv_transformer = 40 MVA
15 | mv_lv_transformer = 630 kVA
16 | mv_line_10kv = NA2XS2Y 3x1x185 RM/25
17 | mv_line_20kv = NA2XS2Y 3x1x240
18 | lv_line = NAYY 4x1x150
19 |
20 | [grid_expansion_allowed_voltage_deviations]
21 |
22 | # allowed voltage deviations
23 | # ==========================
24 |
25 | # voltage at HV/MV station's secondary side
26 | # ------------------------------------------
27 | # hv_mv_trafo_offset:
28 | # offset which is set at HV-MV station
29 | # (pos. if op. voltage is increased, neg. if decreased)
30 | hv_mv_trafo_offset = 0.0
31 |
32 | # hv_mv_trafo_control_deviation:
33 | # control deviation of HV-MV station
34 | # (always pos. in config; pos. or neg. usage depending on case in edisgo)
35 | hv_mv_trafo_control_deviation = 0.0
36 |
37 | # COMBINED MV+LV
38 | # --------------
39 | # max. allowed voltage rise and drop in case voltage band is not allocated to different
40 | # voltage levels
41 | # (values according to DIN EN 50160)
42 | # caution: offset and control deviation at HV-MV station must be considered in calculations!
43 | mv_lv_max_v_rise = 0.1
44 | mv_lv_max_v_drop = 0.1
45 |
46 | # MV ONLY
47 | # -------
48 | # max. allowed voltage rise in MV grids
49 | mv_max_v_rise = 0.05
50 |
51 | # max. allowed voltage drop in MV grids
52 | mv_max_v_drop = 0.015
53 |
54 | # LV ONLY
55 | # -------
56 | # max. allowed voltage rise in LV grids
57 | lv_max_v_rise = 0.035
58 |
59 | # max. allowed voltage rise over MV/LV stations
60 | mv_lv_station_max_v_rise = 0.015
61 |
62 | # max. allowed voltage drop in LV grids
63 | # according to VDE-AR-N 4105
64 | lv_max_v_drop = 0.065
65 |
66 | # max. allowed voltage drop over MV/LV stations
67 | mv_lv_station_max_v_drop = 0.02
68 |
69 | [grid_expansion_load_factors]
70 |
71 | # These are the load factors to use when grid issues in normal grid operation are checked.
72 | # Load factors for n-1 security are set in section grid_expansion_load_factors_n_minus_one.
73 | mv_load_case_transformer = 1.0
74 | mv_load_case_line = 1.0
75 | mv_feed-in_case_transformer = 1.0
76 | mv_feed-in_case_line = 1.0
77 |
78 | lv_load_case_transformer = 1.0
79 | lv_load_case_line = 1.0
80 | lv_feed-in_case_transformer = 1.0
81 | lv_feed-in_case_line = 1.0
82 |
83 | [grid_expansion_load_factors_n_minus_one]
84 |
85 | # These are the load factors to use when n-1 security is checked. Usually, only the
86 | # MV grid components need to be n-1 secure.
87 | # Source: Rehtanz et. al.: "Verteilnetzstudie für das Land Baden-Württemberg", 2017.
88 |
89 | mv_load_case_transformer = 0.5
90 | mv_load_case_line = 0.5
91 | mv_feed-in_case_transformer = 1.0
92 | mv_feed-in_case_line = 1.0
93 |
94 | lv_load_case_transformer = 1.0
95 | lv_load_case_line = 1.0
96 | lv_feed-in_case_transformer = 1.0
97 | lv_feed-in_case_line = 1.0
98 |
99 | # costs
100 | # ============
101 |
102 | [costs_cables]
103 |
104 | # costs in kEUR/km
105 | # costs for cables without earthwork are taken from [1] (costs for standard
106 | # cables are used here as representative since they have average costs), costs
107 | # including earthwork are taken from [2]
108 | # [1] https://www.bundesnetzagentur.de/SharedDocs/Downloads/DE/Sachgebiete/Energie/Unternehmen_Institutionen/Netzentgelte/Anreizregulierung/GA_AnalytischeKostenmodelle.pdf?__blob=publicationFile&v=1
109 | # [2] https://shop.dena.de/fileadmin/denashop/media/Downloads_Dateien/esd/9100_dena-Verteilnetzstudie_Abschlussbericht.pdf
110 | # costs including earthwork costs depend on population density according to [2]
111 | # here "rural" corresponds to a population density of <= 500 people/km²
112 | # and "urban" corresponds to a population density of > 500 people/km²
113 | lv_cable = 9
114 | lv_cable_incl_earthwork_rural = 60
115 | lv_cable_incl_earthwork_urban = 100
116 | mv_cable = 20
117 | mv_cable_incl_earthwork_rural = 80
118 | mv_cable_incl_earthwork_urban = 140
119 |
120 | [costs_transformers]
121 |
122 | # costs in kEUR, source: DENA Verteilnetzstudie
123 | lv = 10
124 | mv = 1000
125 |
--------------------------------------------------------------------------------
/edisgo/config/config_opf_julia_default.cfg:
--------------------------------------------------------------------------------
1 | # This file is part of eDisGo, a python package for distribution grid
2 | # analysis and optimization.
3 | #
4 | # It is developed in the project open_eGo: https://openegoproject.wordpress.com
5 | #
6 | # eDisGo lives on github: https://github.com/openego/edisgo/
7 | # The documentation is available on RTD: https://edisgo.readthedocs.io/en/dev/
8 |
9 | # This file contains path to julia binary and path to project.toml containing correct julia environment
10 | # julia dir should be in users directory
11 |
12 | [julia_dir]
13 |
14 | julia_bin = julia-1.1.0/bin
15 |
--------------------------------------------------------------------------------
/edisgo/config/config_system.cfg:
--------------------------------------------------------------------------------
1 | # This file is part of eDisGo, a python package for distribution grid
2 | # analysis and optimization.
3 | #
4 | # It is developed in the project open_eGo: https://openegoproject.wordpress.com
5 | #
6 | # eDisGo lives on github: https://github.com/openego/edisgo/
7 | # The documentation is available on RTD: https://edisgo.readthedocs.io/en/dev/
8 | #
9 | # CAUTION: This is an internal config file, do not modify unless you know what
10 | # you are doing!
11 |
12 | [user_dirs]
13 |
14 | root_dir = .edisgo
15 | config_dir = config
16 | data_dir = data
17 | log_dir = log
18 | output_dir = output
19 |
20 | [system_dirs]
21 |
22 | equipment_dir = equipment
23 |
24 | [equipment]
25 |
26 | equipment_mv_parameters_transformers = equipment-parameters_MV_transformers.csv
27 | equipment_mv_parameters_cables = equipment-parameters_MV_cables.csv
28 | equipment_mv_parameters_overhead_lines = equipment-parameters_MV_overhead_lines.csv
29 | equipment_lv_parameters_transformers = equipment-parameters_LV_transformers.csv
30 | equipment_lv_parameters_cables = equipment-parameters_LV_cables.csv
31 |
32 | [network_parameters]
33 | freq = 50
34 |
--------------------------------------------------------------------------------
/edisgo/config/config_timeseries_default.cfg:
--------------------------------------------------------------------------------
1 | # This file is part of eDisGo, a python package for distribution grid
2 | # analysis and optimization.
3 | #
4 | # It is developed in the project open_eGo: https://openegoproject.wordpress.com
5 | #
6 | # eDisGo lives on github: https://github.com/openego/edisgo/
7 | # The documentation is available on RTD: https://edisgo.readthedocs.io/en/dev/
8 |
9 | # This file contains relevant data to generate load and feed-in time series.
10 | # Scale factors are used in worst-case scenarios.
11 | # Power factors are used to generate reactive power time series.
12 |
13 | [worst_case_scale_factor]
14 |
15 | # scale factors
16 | # ===========================
17 | # scale factors describe actual power to nominal power ratio of generators and loads in worst-case scenarios
18 | # following values provided by "dena-Verteilnetzstudie. Ausbau- und
19 | # Innovationsbedarf der Stromverteilnetze in Deutschland bis 2030", .p. 98
20 |
21 | # conventional load
22 | # factors taken from "dena-Verteilnetzstudie. Ausbau- und
23 | # Innovationsbedarf der Stromverteilnetze in Deutschland bis 2030", p. 98
24 | mv_feed-in_case_load = 0.15
25 | lv_feed-in_case_load = 0.1
26 | mv_load_case_load = 1.0
27 | lv_load_case_load = 1.0
28 |
29 | # generators
30 | # factors taken from "dena-Verteilnetzstudie. Ausbau- und
31 | # Innovationsbedarf der Stromverteilnetze in Deutschland bis 2030", p. 98
32 | feed-in_case_feed-in_pv = 0.85
33 | feed-in_case_feed-in_wind = 1.0
34 | feed-in_case_feed-in_other = 1.0
35 | load_case_feed-in_pv = 0.0
36 | load_case_feed-in_wind = 0.0
37 | load_case_feed-in_other = 0.0
38 |
39 | # storage units (own values)
40 | feed-in_case_storage = 1.0
41 | load_case_storage = -1.0
42 |
43 | # charging points (temporary own values)
44 |
45 | # simultaneity in feed-in case is in dena study "Integrierte Energiewende" (p. 90) as well assumed to be zero
46 | mv_feed-in_case_cp_home = 0.0
47 | mv_feed-in_case_cp_work = 0.0
48 | mv_feed-in_case_cp_public = 0.0
49 | mv_feed-in_case_cp_hpc = 0.0
50 |
51 | lv_feed-in_case_cp_home = 0.0
52 | lv_feed-in_case_cp_work = 0.0
53 | lv_feed-in_case_cp_public = 0.0
54 | lv_feed-in_case_cp_hpc = 0.0
55 |
56 | # simultaneity in load case should be dependent on number of charging points in the grid
57 | # as well as charging power
58 | # assumed factors for home and work charging higher for LV, as simultaneity of charging
59 | # decreases with the number of charging points
60 |
61 | # simultaneity of 0.2 follows assumptions from dena study "Integrierte Energiewende" (p. 90) where
62 | # simultaneity for 70-500 charging points lies around 20%
63 | mv_load_case_cp_home = 0.2
64 | mv_load_case_cp_work = 0.2
65 | mv_load_case_cp_public = 1.0
66 | mv_load_case_cp_hpc = 1.0
67 |
68 | lv_load_case_cp_home = 1.0
69 | lv_load_case_cp_work = 1.0
70 | lv_load_case_cp_public = 1.0
71 | lv_load_case_cp_hpc = 1.0
72 |
73 | # heat pumps (temporary own values)
74 |
75 | # simultaneity in feed-in case is in dena study "Integrierte Energiewende" (p. 90) as well assumed to be zero
76 | mv_feed-in_case_hp = 0.0
77 | lv_feed-in_case_hp = 0.0
78 |
79 | # simultaneity in load case should be dependent on number of heat pumps in the grid
80 | # simultaneity of 0.8 follows assumptions from dena study "Integrierte Energiewende" (p. 90) where
81 | # simultaneity for 70-500 heat pumps lies around 80%
82 | mv_load_case_hp = 0.8
83 | lv_load_case_hp = 1.0
84 |
85 | [reactive_power_factor]
86 |
87 | # power factors
88 | # ===========================
89 | # power factors used to generate reactive power time series for loads and generators
90 |
91 | mv_generator = 0.9
92 | mv_conventional_load = 0.9
93 | mv_storage_unit = 0.9
94 | mv_charging_point = 1.0
95 | mv_heat_pump = 1.0
96 | lv_generator = 0.95
97 | lv_conventional_load = 0.95
98 | lv_storage_unit = 0.95
99 | lv_charging_point = 1.0
100 | lv_heat_pump = 1.0
101 |
102 | [reactive_power_mode]
103 |
104 | # power factor modes
105 | # ===========================
106 | # power factor modes used to generate reactive power time series for loads and generators
107 |
108 | mv_generator = inductive
109 | mv_conventional_load = inductive
110 | mv_storage_unit = inductive
111 | mv_charging_point = inductive
112 | mv_heat_pump = inductive
113 | lv_generator = inductive
114 | lv_conventional_load = inductive
115 | lv_storage_unit = inductive
116 | lv_charging_point = inductive
117 | lv_heat_pump = inductive
118 |
119 | [demandlib]
120 |
121 | # demandlib data
122 | # ===========================
123 | # data used in the demandlib to generate industrial load profile
124 | # see IndustrialProfile in https://github.com/oemof/demandlib/blob/master/demandlib/particular_profiles.py
125 | # for further information
126 |
127 | # scaling factors for night and day of weekdays and weekend days
128 | week_day = 0.8
129 | week_night = 0.6
130 | weekend_day = 0.6
131 | weekend_night = 0.6
132 | holiday_day = 0.6
133 | holiday_night = 0.6
134 | # tuple specifying the beginning/end of a workday (e.g. 18:00)
135 | day_start = 6:00
136 | day_end = 22:00
137 |
--------------------------------------------------------------------------------
/edisgo/equipment/equipment-parameters_LV_cables.csv:
--------------------------------------------------------------------------------
1 | name,U_n,I_max_th,R_per_km,L_per_km,C_per_km
2 | #-,kV,kA,ohm/km,mH/km,uF/km
3 | NAYY 4x1x300,0.4,0.419,0.1,0.279,0
4 | NAYY 4x1x240,0.4,0.364,0.125,0.254,0
5 | NAYY 4x1x185,0.4,0.313,0.164,0.256,0
6 | NAYY 4x1x150,0.4,0.275,0.206,0.256,0
7 | NAYY 4x1x120,0.4,0.245,0.253,0.256,0
8 | NAYY 4x1x95,0.4,0.215,0.320,0.261,0
9 | NAYY 4x1x50,0.4,0.144,0.449,0.270,0
10 | NAYY 4x1x35,0.4,0.123,0.868,0.271,0
11 |
--------------------------------------------------------------------------------
/edisgo/equipment/equipment-parameters_LV_transformers.csv:
--------------------------------------------------------------------------------
1 | name,S_nom,u_kr,P_k
2 | #,MVA,%,MW
3 | 100 kVA,0.1,4,0.00175
4 | 160 kVA,0.16,4,0.00235
5 | 250 kVA,0.25,4,0.00325
6 | 400 kVA,0.4,4,0.0046
7 | 630 kVA,0.63,4,0.0065
8 | 800 kVA,0.8,6,0.0084
9 | 1000 kVA,1.0,6,0.00105
10 |
--------------------------------------------------------------------------------
/edisgo/equipment/equipment-parameters_MV_cables.csv:
--------------------------------------------------------------------------------
1 | name,U_n,I_max_th,R_per_km,L_per_km,C_per_km
2 | #-,kV,kA,ohm/km,mH/km,uF/km
3 | NA2XS2Y 3x1x185 RM/25,10,0.357,0.164,0.38,0.41
4 | NA2XS2Y 3x1x240 RM/25,10,0.417,0.125,0.36,0.47
5 | NA2XS2Y 3x1x300 RM/25,10,0.466,0.1,0.35,0.495
6 | NA2XS2Y 3x1x400 RM/35,10,0.535,0.078,0.34,0.57
7 | NA2XS2Y 3x1x500 RM/35,10,0.609,0.061,0.32,0.63
8 | NA2XS2Y 3x1x150 RE/25,20,0.319,0.206,0.4011,0.24
9 | NA2XS2Y 3x1x240,20,0.417,0.13,0.3597,0.304
10 | NA2XS(FL)2Y 3x1x300 RM/25,20,0.476,0.1,0.37,0.25
11 | NA2XS(FL)2Y 3x1x400 RM/35,20,0.525,0.078,0.36,0.27
12 | NA2XS(FL)2Y 3x1x500 RM/35,20,0.598,0.06,0.34,0.3
13 |
--------------------------------------------------------------------------------
/edisgo/equipment/equipment-parameters_MV_overhead_lines.csv:
--------------------------------------------------------------------------------
1 | name,U_n,I_max_th,R_per_km,L_per_km,C_per_km
2 | #-,kV,kA,ohm/km,mH/km,uF/km
3 | 48-AL1/8-ST1A,10,0.21,0.35,1.11,0.0104
4 | 94-AL1/15-ST1A,10,0.35,0.33,1.05,0.0112
5 | 122-AL1/20-ST1A,10,0.41,0.31,0.99,0.0115
6 | 48-AL1/8-ST1A,20,0.21,0.37,1.18,0.0098
7 | 94-AL1/15-ST1A,20,0.35,0.35,1.11,0.0104
8 | 122-AL1/20-ST1A,20,0.41,0.34,1.08,0.0106
9 |
--------------------------------------------------------------------------------
/edisgo/equipment/equipment-parameters_MV_transformers.csv:
--------------------------------------------------------------------------------
1 | name,S_nom
2 | #,MVA
3 | 20 MVA,20
4 | 32 MVA,32
5 | 40 MVA,40
6 | 63 MVA,63
7 |
--------------------------------------------------------------------------------
/edisgo/equipment/equipment_data.meta:
--------------------------------------------------------------------------------
1 | {"equipment_mv_parameters_trafos": "equipment-parameters_MV_transformers.csv", "equipment_mv_parameters_cables": "equipment-parameters_MV_cables.csv", "equipment_mv_parameters_lines": "equipment-parameters_MV_overhead_lines.csv", "equipment_lv_parameters_trafos": "equipment-parameters_LV_transformers.csv", "equipment_lv_parameters_cables": "equipment-parameters_LV_cables.csv", "Notes": "Note that only values used for calculation are saved in this table, for more values look into source. Only insert literature values here, calculations in code for better comprehensibility.", "Sources": {"LV_transformers": "Torsten Werth, Netzberechnung mit Erzeugungsprofilen- Grundlagen, Berechnung, Anwendung, Springer,2016", "LV_cables": "FaberKabel Starkstromkabel NAYY-J/-O nach VDE 0276-603"}}
2 |
--------------------------------------------------------------------------------
/edisgo/flex_opt/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/edisgo/flex_opt/__init__.py
--------------------------------------------------------------------------------
/edisgo/flex_opt/exceptions.py:
--------------------------------------------------------------------------------
1 | class Error(Exception):
2 | """Base class for exceptions in this module."""
3 |
4 | pass
5 |
6 |
7 | class MaximumIterationError(Error):
8 | """
9 | Exception raised when maximum number of iterations in network reinforcement
10 | is exceeded.
11 |
12 | Attributes
13 | -----------
14 | message : str
15 | Explanation of the error
16 |
17 | """
18 |
19 | def __init__(self, message):
20 | self.message = message
21 |
22 |
23 | class ImpossibleVoltageReduction(Error):
24 | """
25 | Exception raised when voltage issue cannot be solved.
26 |
27 | Attributes
28 | -----------
29 | message : str
30 | Explanation of the error
31 |
32 | """
33 |
34 | def __init__(self, message):
35 | self.message = message
36 |
37 |
38 | class InfeasibleModelError(Error):
39 | """
40 | Exception raised when OPF can not be solved.
41 |
42 | Attributes
43 | -----------
44 | message : str
45 | Explanation of the error
46 |
47 | """
48 |
49 | def __init__(self, message):
50 | self.message = message
51 |
--------------------------------------------------------------------------------
/edisgo/flex_opt/heat_pump_operation.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | import pandas as pd
4 |
5 | logger = logging.getLogger("edisgo")
6 |
7 |
8 | def operating_strategy(
9 | edisgo_obj,
10 | strategy="uncontrolled",
11 | heat_pump_names=None,
12 | ):
13 | """
14 | Applies operating strategy to set electrical load time series of heat pumps.
15 |
16 | See :attr:`~.edisgo.EDisGo.apply_heat_pump_operating_strategy` for more information.
17 |
18 | Parameters
19 | ----------
20 | edisgo_obj : :class:`~.EDisGo`
21 | strategy : str
22 | Defines the operating strategy to apply. See `strategy` parameter in
23 | :attr:`~.edisgo.EDisGo.apply_heat_pump_operating_strategy` for more information.
24 | Default: 'uncontrolled'.
25 | heat_pump_names : list(str) or None
26 | Defines for which heat pumps to apply operating strategy. See `heat_pump_names`
27 | parameter in :attr:`~.edisgo.EDisGo.apply_heat_pump_operating_strategy` for
28 | more information. Default: None.
29 |
30 | """
31 | if heat_pump_names is None:
32 | heat_pump_names = edisgo_obj.heat_pump.cop_df.columns
33 |
34 | if strategy == "uncontrolled":
35 | ts = (
36 | edisgo_obj.heat_pump.heat_demand_df.loc[:, heat_pump_names]
37 | / edisgo_obj.heat_pump.cop_df.loc[:, heat_pump_names]
38 | )
39 | edisgo_obj.timeseries.add_component_time_series(
40 | "loads_active_power",
41 | ts,
42 | )
43 | else:
44 | raise ValueError(
45 | f"Heat pump operating strategy {strategy} is not a valid option. "
46 | f"The only operating strategy currently implemented is 'uncontrolled'."
47 | )
48 |
49 | # set reactive power time series to 0 Mvar
50 | edisgo_obj.timeseries.add_component_time_series(
51 | "loads_reactive_power",
52 | pd.DataFrame(
53 | data=0.0,
54 | index=edisgo_obj.timeseries.timeindex,
55 | columns=heat_pump_names,
56 | ),
57 | )
58 |
59 | logger.debug(f"Heat pump operating strategy {strategy} completed.")
60 |
--------------------------------------------------------------------------------
/edisgo/io/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/edisgo/io/__init__.py
--------------------------------------------------------------------------------
/edisgo/io/ding0_import.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | import pandas as pd
4 |
5 | from pypsa import Network as PyPSANetwork
6 |
7 | from edisgo.network.grids import MVGrid
8 |
9 | if "READTHEDOCS" not in os.environ:
10 | from shapely.wkt import loads as wkt_loads
11 |
12 | import logging
13 |
14 | logger = logging.getLogger(__name__)
15 |
16 |
17 | def import_ding0_grid(path, edisgo_obj, legacy_ding0_grids=True):
18 | """
19 | Import an eDisGo network topology from
20 | `Ding0 data `_.
21 |
22 | This import method is specifically designed to load network topology data in
23 | the format as `Ding0 `_ provides it via
24 | csv files.
25 |
26 | Parameters
27 | ----------
28 | path : str
29 | Path to ding0 network csv files.
30 | edisgo_obj : :class:`~.EDisGo`
31 | The eDisGo data container object.
32 | legacy_ding0_grids : bool
33 | Allow import of old ding0 grids. Default: True.
34 |
35 | """
36 |
37 | def sort_transformer_buses(transformers_df):
38 | """
39 | Sort buses of inserted transformers in a way that bus1 always
40 | represents secondary side of transformer.
41 | """
42 | voltage_bus0 = edisgo_obj.topology.buses_df.loc[
43 | transformers_df.bus0
44 | ].v_nom.values
45 | voltage_bus1 = edisgo_obj.topology.buses_df.loc[
46 | transformers_df.bus1
47 | ].v_nom.values
48 | transformers_df.loc[
49 | voltage_bus1 > voltage_bus0, ["bus0", "bus1"]
50 | ] = transformers_df.loc[voltage_bus1 > voltage_bus0, ["bus1", "bus0"]].values
51 | return transformers_df
52 |
53 | def sort_hvmv_transformer_buses(transformers_df):
54 | """
55 | Sort buses of inserted HV/MV transformers in a way that bus1 always
56 | represents secondary side of transformer.
57 | """
58 | for transformer in transformers_df.index:
59 | if (
60 | transformers_df.at[transformer, "bus1"]
61 | in edisgo_obj.topology.buses_df.index
62 | ):
63 | continue
64 |
65 | transformers_df.loc[transformer, ["bus0", "bus1"]] = transformers_df.loc[
66 | transformer, ["bus1", "bus0"]
67 | ].values
68 |
69 | return transformers_df
70 |
71 | grid = PyPSANetwork()
72 | grid.import_from_csv_folder(path)
73 |
74 | # write dataframes to edisgo_obj
75 | edisgo_obj.topology.buses_df = grid.buses[edisgo_obj.topology.buses_df.columns]
76 | edisgo_obj.topology.lines_df = grid.lines[edisgo_obj.topology.lines_df.columns]
77 | if legacy_ding0_grids:
78 | logger.debug("Use ding0 legacy grid import.")
79 | # rename column peak_load to p_set
80 | grid.loads = grid.loads.drop(columns="p_set").rename(
81 | columns={"peak_load": "p_set"}
82 | )
83 | # set loads without type information to be conventional loads
84 | # this is done, as older ding0 versions do not provide information on the type
85 | # of load and can be done as these ding0 grids only contain conventional loads
86 | loads_without_type = grid.loads[
87 | (grid.loads.type.isnull()) | (grid.loads.type == "")
88 | ].index
89 | grid.loads.loc[loads_without_type, "type"] = "conventional_load"
90 | # rename retail to cts, as it is in newer ding0 versions called cts
91 | grid.loads.replace(to_replace=["retail"], value="cts", inplace=True)
92 | # set up columns that are added in new ding0 version
93 | grid.loads["building_id"] = None
94 | grid.loads["number_households"] = None
95 | grid.generators["source_id"] = None
96 | else:
97 | edisgo_obj.topology.buses_df["in_building"] = False
98 | grid.generators = grid.generators.rename(columns={"gens_id": "source_id"})
99 | edisgo_obj.topology.loads_df = grid.loads[edisgo_obj.topology.loads_df.columns]
100 | # drop slack generator from generators
101 | slack = grid.generators.loc[grid.generators.control == "Slack"].index
102 | grid.generators.drop(slack, inplace=True)
103 | edisgo_obj.topology.generators_df = grid.generators[
104 | edisgo_obj.topology.generators_df.columns
105 | ]
106 | edisgo_obj.topology.storage_units_df = grid.storage_units[
107 | edisgo_obj.topology.storage_units_df.columns
108 | ]
109 | edisgo_obj.topology.transformers_df = sort_transformer_buses(
110 | grid.transformers.drop(labels=["x_pu", "r_pu"], axis=1).rename(
111 | columns={"r": "r_pu", "x": "x_pu"}
112 | )[edisgo_obj.topology.transformers_df.columns]
113 | )
114 | edisgo_obj.topology.transformers_hvmv_df = sort_hvmv_transformer_buses(
115 | pd.read_csv(os.path.join(path, "transformers_hvmv.csv"), index_col=[0]).rename(
116 | columns={"r": "r_pu", "x": "x_pu"}
117 | )
118 | )
119 | edisgo_obj.topology.switches_df = pd.read_csv(
120 | os.path.join(path, "switches.csv"), index_col=[0]
121 | )
122 |
123 | edisgo_obj.topology.grid_district = {
124 | "population": grid.mv_grid_district_population,
125 | "geom": wkt_loads(grid.mv_grid_district_geom),
126 | "srid": grid.srid,
127 | }
128 |
129 | # set up medium voltage grid
130 | mv_grid_id = list(set(grid.buses.mv_grid_id))[0]
131 | edisgo_obj.topology.mv_grid = MVGrid(id=mv_grid_id, edisgo_obj=edisgo_obj)
132 |
133 | # check data integrity
134 | edisgo_obj.topology.check_integrity()
135 |
--------------------------------------------------------------------------------
/edisgo/network/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/edisgo/network/__init__.py
--------------------------------------------------------------------------------
/edisgo/opf/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/edisgo/opf/__init__.py
--------------------------------------------------------------------------------
/edisgo/opf/eDisGo_OPF.jl/Main.jl:
--------------------------------------------------------------------------------
1 | cd(dirname(@__FILE__))
2 | using Pkg
3 | Pkg.activate("")
4 | Pkg.instantiate()
5 | try
6 | using eDisGo_OPF
7 | using PowerModels
8 | using Ipopt
9 | using JuMP
10 | using JSON
11 | using Gurobi
12 | catch e
13 | Pkg.instantiate()
14 | using eDisGo_OPF
15 | using PowerModels
16 | using Ipopt
17 | using JuMP
18 | using JSON
19 | using Gurobi
20 | end
21 |
22 |
23 |
24 | PowerModels.logger_config!("debug")
25 | json_str = readline(stdin)
26 | ding0_grid = ARGS[1]
27 | results_path = ARGS[2]
28 | method = ARGS[3]
29 | silence_moi = ARGS[4].=="True"
30 | warm_start = ARGS[5].=="True"
31 |
32 | # Set solver attributes
33 | const ipopt = optimizer_with_attributes(Ipopt.Optimizer, MOI.Silent() => silence_moi, "sb" => "yes", "tol"=>1e-6)
34 | function optimize_edisgo()
35 | # read in data and create multinetwork
36 | gurobi = optimizer_with_attributes(Gurobi.Optimizer, MOI.Silent() => silence_moi, "FeasibilityTol"=>1e-4, "BarQCPConvTol"=>1e-4, "BarConvTol"=>1e-4, "BarHomogeneous"=>1)
37 | data_edisgo = eDisGo_OPF.parse_json(json_str)
38 | data_edisgo_mn = PowerModels.make_multinetwork(data_edisgo)
39 |
40 | if method == "soc" # Second order cone
41 | # Solve SOC model
42 | println("Starting convex SOC AC-OPF with Gurobi.")
43 | result_soc, pm = eDisGo_OPF.solve_mn_opf_bf_flex(data_edisgo_mn, SOCBFPowerModelEdisgo, gurobi)
44 | #println("Termination status: "*result_soc["termination_status"])
45 | if result_soc["termination_status"] != MOI.OPTIMAL
46 | # if result_soc["termination_status"] == MOI.SUBOPTIMAL_TERMINATION
47 | # PowerModels.update_data!(data_edisgo_mn, result_soc["solution"])
48 | # else
49 | JuMP.compute_conflict!(pm.model)
50 | if MOI.get(pm.model, MOI.ConflictStatus()) == MOI.CONFLICT_FOUND
51 | iis_model, _ = copy_conflict(pm.model)
52 | print(iis_model)
53 | end
54 | #end
55 | elseif result_soc["termination_status"] == MOI.OPTIMAL
56 | # Check if SOC constraint is tight
57 | soc_tight, soc_dict = eDisGo_OPF.check_SOC_equality(result_soc, data_edisgo)
58 | # Save SOC violations if SOC is not tight
59 | if !soc_tight
60 | open(joinpath(results_path, ding0_grid*"_"*join(data_edisgo["flexibilities"])*".json"), "w") do f
61 | write(f, JSON.json(soc_dict))
62 | end
63 | println("SOC solution is not tight!")
64 | end
65 | PowerModels.update_data!(data_edisgo_mn, result_soc["solution"])
66 | data_edisgo_mn["solve_time"] = result_soc["solve_time"]
67 | data_edisgo_mn["status"] = result_soc["termination_status"]
68 | data_edisgo_mn["solver"] = "Gurobi"
69 | if soc_tight & warm_start
70 | println("Starting warm-start non-convex AC-OPF with IPOPT.")
71 | set_ac_bf_start_values!(data_edisgo_mn["nw"]["1"])
72 | result_nc_ws, pm = eDisGo_OPF.solve_mn_opf_bf_flex(data_edisgo_mn, NCBFPowerModelEdisgo, ipopt)
73 | PowerModels.update_data!(data_edisgo_mn, result_nc_ws["solution"])
74 | data_edisgo_mn["solve_time"] = result_nc_ws["solve_time"]
75 | data_edisgo_mn["status"] = result_nc_ws["termination_status"]
76 | data_edisgo_mn["solver"] = "Ipopt"
77 | end
78 | end
79 | elseif method == "nc" # Non-Convex
80 | # Solve NC model
81 | println("Starting cold-start non-convex AC-OPF with IPOPT.")
82 | result, pm = eDisGo_OPF.solve_mn_opf_bf_flex(data_edisgo_mn, NCBFPowerModelEdisgo, ipopt)
83 | PowerModels.update_data!(data_edisgo_mn, result["solution"])
84 | data_edisgo_mn["solve_time"] = result["solve_time"]
85 | data_edisgo_mn["status"] = result["termination_status"]
86 | data_edisgo_mn["solver"] = "Ipopt"
87 | end
88 |
89 | # Update network data with optimization results and print to stdout
90 | print(JSON.json(data_edisgo_mn))
91 | end
92 |
93 | if abspath(PROGRAM_FILE) == @__FILE__
94 | optimize_edisgo()
95 | end
96 |
--------------------------------------------------------------------------------
/edisgo/opf/eDisGo_OPF.jl/Project.toml:
--------------------------------------------------------------------------------
1 | name = "eDisGo_OPF"
2 | uuid = "8c767188-7e8f-4256-9955-fc0aecae9b11"
3 | authors = ["Maike Held"]
4 | version = "0.1.0"
5 |
6 | [deps]
7 | Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
8 | Gurobi = "2e9cd046-0924-5485-92f1-d5272153d98b"
9 | IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a"
10 | InfrastructureModels = "2030c09a-7f63-5d83-885d-db604e0e9cc0"
11 | Ipopt = "b6b21f68-93f8-5de0-b562-5493be1d77c9"
12 | JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
13 | JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
14 | Memento = "f28f55f0-a522-5efc-85c2-fe41dfb9b2d9"
15 | #Mosek = "6405355b-0ac2-5fba-af84-adbd65488c0e"
16 | #MosekTools = "1ec41992-ff65-5c91-ac43-2df89e9693a4"
17 | PowerModels = "c36e90e8-916a-50a6-bd94-075b64ef4655"
18 |
19 | [compat]
20 | PowerModels = "0.19.6"
21 | julia = "1.6"
22 |
--------------------------------------------------------------------------------
/edisgo/opf/eDisGo_OPF.jl/src/core/constraint.jl:
--------------------------------------------------------------------------------
1 | """ Creates constraints for storage operations (battery, heat, DSM)"""
2 |
3 | function constraint_store_state_initial(pm::AbstractBFModelEdisgo, n::Int, i::Int, energy, charge_eff, discharge_eff, time_elapsed, kind, p_loss)
4 | if kind == "storage"
5 | ps_1 = PowerModels.var(pm, n, :ps, i)
6 | se = PowerModels.var(pm, n, :se, i)
7 | se_end = PowerModels.var(pm, length(PowerModels.nw_ids(pm)), :se, i)
8 | soc_initial = PowerModels.ref(pm, n, :storage)[i]["soc_initial"]
9 | soc_end = PowerModels.ref(pm, n, :storage)[i]["soc_end"]
10 | JuMP.@constraint(pm.model, se - soc_initial == - time_elapsed * ps_1) # Eq. (3.10) i.V.m. Eq. (3.9) für t = 1 bzw. = 0
11 | JuMP.@constraint(pm.model, se_end == soc_end) # Eq. (3.9) für t = tau
12 | elseif kind == "heat_storage"
13 | phs_1 = PowerModels.var(pm, n, :phs, i)
14 | hse = PowerModels.var(pm, n, :hse, i)
15 | hse_end = PowerModels.var(pm, length(PowerModels.nw_ids(pm)), :hse, i)
16 | soc_initial = PowerModels.ref(pm, n, :heat_storage)[i]["soc_initial"]
17 | soc_end = PowerModels.ref(pm, n, :heat_storage)[i]["soc_end"]
18 | JuMP.@constraint(pm.model, hse - soc_initial == - time_elapsed * phs_1) # Eq. (3.23) i.V.m. Eq. (3.22) (t=1)
19 | JuMP.@constraint(pm.model, hse_end == soc_end) # Eq. (3.22) für t = tau
20 | elseif kind == "dsm"
21 | dsme = PowerModels.var(pm, n, :dsme, i)
22 | dsme_end = PowerModels.var(pm, length(PowerModels.nw_ids(pm)), :dsme, i)
23 | pdsm_1 = PowerModels.var(pm, n, :pdsm, i)
24 | JuMP.@constraint(pm.model, dsme - energy == + time_elapsed * pdsm_1) # Eq. (3.33) für t=1 (und Eq. (3.32) für t = 0, da energy=e(0) = 0)
25 | JuMP.@constraint(pm.model, dsme_end == 0) # Eq. (3.32) für t = tau
26 | end
27 | end
28 |
29 |
30 | function constraint_store_state(pm::AbstractBFModelEdisgo, n_1::Int, n_2::Int, i::Int, charge_eff, discharge_eff, time_elapsed, kind, p_loss)
31 | if kind == "storage"
32 | ps_2 = PowerModels.var(pm, n_2, :ps, i)
33 | se_2 = PowerModels.var(pm, n_2, :se, i)
34 | se_1 = PowerModels.var(pm, n_1, :se, i)
35 |
36 | JuMP.@constraint(pm.model, se_2 - se_1 == - time_elapsed*ps_2) # Eq. (3.10)
37 | elseif kind == "heat_storage"
38 | phs_2 = PowerModels.var(pm, n_2, :phs, i)
39 | hse_2 = PowerModels.var(pm, n_2, :hse, i)
40 | hse_1 = PowerModels.var(pm, n_1, :hse, i)
41 |
42 | JuMP.@constraint(pm.model, hse_2 - hse_1 * (1 - p_loss)^(1/24) == - time_elapsed*phs_2) # Eq. (3.23)
43 | elseif kind == "dsm"
44 | pdsm_2 = PowerModels.var(pm, n_2, :pdsm, i)
45 | dsme_2 = PowerModels.var(pm, n_2, :dsme, i)
46 | dsme_1 = PowerModels.var(pm, n_1, :dsme, i)
47 |
48 | JuMP.@constraint(pm.model, dsme_2 - dsme_1 == time_elapsed*pdsm_2) # Eq. (3.33)
49 | end
50 | end
51 |
52 | """ Creates constraints for EV charging per charging park"""
53 |
54 | function constraint_cp_state_initial(pm::AbstractBFModelEdisgo, n::Int, i::Int, eta)
55 | if haskey(PowerModels.ref(pm, n), :time_elapsed)
56 | time_elapsed = PowerModels.ref(pm, n, :time_elapsed)
57 | else
58 | Memento.warn(_LOGGER, "network data should specify time_elapsed, using 1.0 as a default")
59 | time_elapsed = 1.0
60 | end
61 |
62 | cp = PowerModels.ref(pm, n, :electromobility, i)
63 | cpe = PowerModels.var(pm, n, :cpe, i)
64 | pcp_1 = PowerModels.var(pm, n, :pcp, i)
65 | JuMP.@constraint(pm.model, cpe == 0.5*(cp["e_min"]+cp["e_max"]) + time_elapsed * eta * pcp_1) # Eq. (3.25)
66 |
67 | end
68 |
69 | function constraint_cp_state(pm::AbstractBFModelEdisgo, n_1::Int, n_2::Int, i::Int, eta)
70 | if haskey(PowerModels.ref(pm, n_1), :time_elapsed)
71 | time_elapsed = PowerModels.ref(pm, n_1, :time_elapsed)
72 | else
73 | Memento.warn(_LOGGER, "network data should specify time_elapsed, using 1.0 as a default")
74 | time_elapsed = 1.0
75 | end
76 |
77 | pcp_2 = PowerModels.var(pm, n_2, :pcp, i)
78 | cpe_2 = PowerModels.var(pm, n_2, :cpe, i)
79 | cpe_1 = PowerModels.var(pm, n_1, :cpe, i)
80 |
81 | JuMP.@constraint(pm.model, cpe_2 - cpe_1 == time_elapsed * eta * pcp_2) # Eq. (3.26)
82 |
83 | if n_2 == length(collect(PowerModels.nw_ids(pm)))
84 | cp = PowerModels.ref(pm, length(collect(PowerModels.nw_ids(pm))), :electromobility, i)
85 | JuMP.@constraint(pm.model, cpe_2 == 0.5*(cp["e_min"]+cp["e_max"])) # Eq. (3.25) für t=tau
86 | end
87 | end
88 |
89 | """ Creates constraints for heat pump operation"""
90 |
91 | function constraint_hp_operation(pm::AbstractBFModelEdisgo, i::Int, nw::Int=nw_id_default)
92 | hp = PowerModels.ref(pm, nw, :heatpumps, i)
93 | php = PowerModels.var(pm, nw, :php, i)
94 | phs = PowerModels.var(pm, nw, :phs, i)
95 | phss = PowerModels.var(pm, nw, :phss, i)
96 | phps2 = PowerModels.var(pm, nw, :phps2, i)
97 |
98 |
99 | JuMP.@constraint(pm.model, hp["cop"] * (php+phps2) == hp["pd"] + phss - phs)
100 |
101 | end
102 |
103 | """ Creates constraints for high voltage grid requirements"""
104 |
105 | function constraint_HV_requirements(pm::AbstractBFModelEdisgo, i::Int, nw::Int=nw_id_default)
106 | hv_req = PowerModels.ref(pm, nw, :HV_requirements, i)
107 | phvs = PowerModels.var(pm, nw, :phvs, i)
108 |
109 | if hv_req["name"] == "dsm"
110 | pflex = PowerModels.var(pm, nw, :pdsm)
111 | elseif hv_req["name"] == "curt"
112 | pflex = PowerModels.var(pm, nw, :pgc)
113 | elseif hv_req["name"] == "storage" # ToDo: virtual branch p variable instead of ps
114 | # branch = PowerModels.ref(pm, nw, :branch)
115 | # for (i, b) in branch
116 | # if b["storage"]
117 | # Hier die pf Variablen (negativ!) aufsummieren
118 | # end
119 | # end
120 | pflex = PowerModels.var(pm, nw, :ps)
121 | elseif hv_req["name"] == "hp"
122 | pflex = PowerModels.var(pm, nw, :php)
123 | elseif hv_req["name"] == "cp"
124 | pflex = PowerModels.var(pm, nw, :pcp)
125 | end
126 | JuMP.@constraint(pm.model, sum(pflex) + phvs == hv_req["P"])
127 |
128 | end
129 |
--------------------------------------------------------------------------------
/edisgo/opf/eDisGo_OPF.jl/src/core/constraint_template.jl:
--------------------------------------------------------------------------------
1 | "power balance for radial branch flow model"
2 | function constraint_power_balance_bf(pm::AbstractBFModelEdisgo, i::Int; nw::Int=nw_id_default)
3 | bus_arcs_to = PowerModels.ref(pm, nw, :bus_arcs_to, i)
4 | bus_arcs_from = PowerModels.ref(pm, nw, :bus_arcs_from, i)
5 | bus_lines_to = PowerModels.ref(pm, nw, :bus_lines_to, i)
6 | bus_gens = PowerModels.ref(pm, nw, :bus_gens, i)
7 | bus_gens_nd = PowerModels.ref(pm, nw, :bus_gens_nd, i)
8 | bus_gens_slack = PowerModels.ref(pm, nw, :bus_gens_slack, i)
9 | bus_loads = PowerModels.ref(pm, nw, :bus_loads, i)
10 | bus_storage = PowerModels.ref(pm, nw, :bus_storage, i)
11 | bus_dsm = PowerModels.ref(pm, nw, :bus_dsm, i)
12 | bus_hps = PowerModels.ref(pm, nw, :bus_hps, i)
13 | bus_cps = PowerModels.ref(pm, nw, :bus_cps, i)
14 |
15 |
16 | branch_r = Dict(k => PowerModels.ref(pm, nw, :branch, k, "br_r") for k in bus_lines_to)
17 | branch_x = Dict(k => PowerModels.ref(pm, nw, :branch, k, "br_x") for k in bus_lines_to)
18 | branch_strg_pf = Dict(k => PowerModels.ref(pm, nw, :branch, k, "storage_pf") for k in bus_lines_to)
19 |
20 | bus_pg = Dict(k => PowerModels.ref(pm, nw, :gen, k, "pg") for k in bus_gens)
21 | bus_qg = Dict(k => PowerModels.ref(pm, nw, :gen, k, "qg") for k in bus_gens)
22 |
23 | bus_pg_nd = Dict(k => PowerModels.ref(pm, nw, :gen_nd, k, "pg") for k in bus_gens_nd)
24 | bus_qg_nd = Dict(k => PowerModels.ref(pm, nw, :gen_nd, k, "qg") for k in bus_gens_nd)
25 |
26 | bus_pd = Dict(k => PowerModels.ref(pm, nw, :load, k, "pd") for k in bus_loads)
27 | bus_qd = Dict(k => PowerModels.ref(pm, nw, :load, k, "qd") for k in bus_loads)
28 |
29 | bus_storage_pf = Dict(k => tan(acos(PowerModels.ref(pm, nw, :storage, k, "pf")))*PowerModels.ref(pm, nw, :storage, k, "sign") for k in bus_storage)
30 | bus_dsm_pf = Dict(k => tan(acos(PowerModels.ref(pm, nw, :dsm, k, "pf")))*PowerModels.ref(pm, nw, :dsm, k, "sign") for k in bus_dsm)
31 | bus_hps_pf = Dict(k => tan(acos(PowerModels.ref(pm, nw, :heatpumps, k, "pf")))*PowerModels.ref(pm, nw, :heatpumps, k, "sign") for k in bus_hps)
32 | bus_cps_pf = Dict(k => tan(acos(PowerModels.ref(pm, nw, :electromobility, k, "pf")))*PowerModels.ref(pm, nw, :electromobility, k, "sign") for k in bus_cps)
33 | bus_gen_nd_pf = Dict(k => tan(acos(PowerModels.ref(pm, nw, :gen_nd, k, "pf")))*PowerModels.ref(pm, nw, :gen_nd, k, "sign") for k in bus_gens_nd)
34 | bus_gen_d_pf = Dict(k => tan(acos(PowerModels.ref(pm, nw, :gen, k, "pf")))*PowerModels.ref(pm, nw, :gen, k, "sign") for k in bus_gens)
35 | bus_loads_pf = Dict(k => tan(acos(PowerModels.ref(pm, nw, :load, k, "pf")))*PowerModels.ref(pm, nw, :load, k, "sign") for k in bus_loads)
36 |
37 | constraint_power_balance(pm, nw, i, bus_gens, bus_gens_nd, bus_gens_slack, bus_loads, bus_arcs_to, bus_arcs_from, bus_lines_to, bus_storage, bus_pg, bus_qg, bus_pg_nd, bus_qg_nd, bus_pd, bus_qd, branch_r, branch_x, bus_dsm, bus_hps, bus_cps, bus_storage_pf, bus_dsm_pf, bus_hps_pf, bus_cps_pf, bus_gen_nd_pf, bus_gen_d_pf, bus_loads_pf, branch_strg_pf)
38 | end
39 |
40 | ""
41 | function constraint_voltage_magnitude_difference_radial(pm::AbstractBFModelEdisgo, i::Int; nw::Int=nw_id_default)
42 | branch = PowerModels.ref(pm, nw, :branch, i)
43 | f_bus = branch["f_bus"]
44 | t_bus = branch["t_bus"]
45 | f_idx = (i, f_bus, t_bus)
46 | t_idx = (i, t_bus, f_bus)
47 |
48 | r = branch["br_r"]
49 | x = branch["br_x"]
50 | tm = branch["tap"]
51 | if !(branch["storage"])
52 | constraint_voltage_magnitude_difference(pm, nw, i, f_bus, t_bus, f_idx, t_idx, r, x, tm)
53 | end
54 | end
55 |
56 | function constraint_store_state(pm::AbstractBFModelEdisgo, i::Int; nw::Int=nw_id_default, kind::String)
57 | storage = PowerModels.ref(pm, nw, Symbol(kind), i)
58 |
59 | if kind == "dsm"
60 | p_loss = 0
61 | elseif kind in("storage", "heat_storage")
62 | p_loss = storage["p_loss"]
63 | end
64 |
65 | if haskey(PowerModels.ref(pm, nw), :time_elapsed)
66 | time_elapsed = PowerModels.ref(pm, nw, :time_elapsed)
67 | else
68 | Memento.warn(_LOGGER, "network data should specify time_elapsed, using 1.0 as a default")
69 | time_elapsed = 1.0
70 | end
71 |
72 | constraint_store_state_initial(pm, nw, i, storage["energy"], storage["charge_efficiency"], storage["discharge_efficiency"], time_elapsed, kind, p_loss)
73 | end
74 |
75 | ""
76 | function constraint_store_state(pm::AbstractBFModelEdisgo, i::Int, nw_1::Int, nw_2::Int, kind::String)
77 | storage = PowerModels.ref(pm, nw_2, Symbol(kind), i)
78 |
79 | if kind == "dsm"
80 | p_loss = 0
81 | elseif kind in("storage", "heat_storage")
82 | p_loss = storage["p_loss"]
83 | end
84 |
85 | if haskey(PowerModels.ref(pm, nw_2), :time_elapsed)
86 | time_elapsed = PowerModels.ref(pm, nw_2, :time_elapsed)
87 | else
88 | Memento.warn(_LOGGER, "network $(nw_2) should specify time_elapsed, using 1.0 as a default")
89 | time_elapsed = 1.0
90 | end
91 |
92 | if haskey(PowerModels.ref(pm, nw_1, Symbol(kind)), i)
93 | constraint_store_state(pm, nw_1, nw_2, i, storage["charge_efficiency"], storage["discharge_efficiency"], time_elapsed, kind, p_loss)
94 | else
95 | # if the storage device has status=0 in nw_1, then the stored energy variable will not exist. Initialize storage from data model instead.
96 | Memento.warn(_LOGGER, "storage component $(i) was not found in network $(nw_1) while building constraint_storage_state between networks $(nw_1) and $(nw_2). Using the energy value from the storage component in network $(nw_2) instead")
97 | constraint_store_state_initial(pm, nw_2, i, storage["energy"], storage["charge_efficiency"], storage["discharge_efficiency"], time_elapsed, kind, p_loss)
98 | end
99 | end
100 |
101 | function constraint_model_current(pm::AbstractPowerModel; nw::Int=nw_id_default)
102 | eDisGo_OPF.constraint_model_current(pm, nw)
103 | end
104 |
--------------------------------------------------------------------------------
/edisgo/opf/eDisGo_OPF.jl/src/core/data.jl:
--------------------------------------------------------------------------------
1 | function set_ac_bf_start_values!(network::Dict{String,<:Any})
2 |
3 | for (i,gen) in network["gen_nd"]
4 | gen["pgc_start"] = gen["pgc"]
5 | end
6 |
7 | for (i,gen) in network["gen_slack"]
8 | gen["pgs_start"] = gen["pgs"]
9 | gen["qgs_start"] = gen["qgs"]
10 | end
11 |
12 | for (i,dsm) in network["dsm"]
13 | dsm["pdsm_start"] = dsm["pdsm"]
14 | dsm["dsme_start"] = dsm["dsme"]
15 | end
16 |
17 | for (i,s) in network["storage"]
18 | s["ps_start"] = s["ps"]
19 | s["se_start"] = s["se"]
20 | end
21 |
22 | for (i,cp) in network["electromobility"]
23 | cp["pcp_start"] = cp["pcp"]
24 | end
25 |
26 | for (i,hp) in network["heatpumps"]
27 | hp["php_start"] = hp["php"]
28 | end
29 |
30 | for (i,hs) in network["heat_storage"]
31 | hs["phs_start"] = hs["phs"]
32 | hs["hse_start"] = hs["hse"]
33 | end
34 |
35 | end
36 |
37 | """
38 | checks bus types are suitable for a power flow study, if not, fixes them.
39 |
40 | the primary checks are that all type 2 buses (i.e., PV) have a connected and
41 | active generator and there is a single type 3 bus (i.e., slack bus) with an
42 | active connected generator.
43 |
44 | assumes that the network is a single connected component
45 | """
46 | function correct_bus_types!(data::Dict{String,<:Any})
47 | apply_pm!(eDisGo_OPF._correct_bus_types!, data)
48 | end
49 |
50 | ""
51 | function _correct_bus_types!(pm_data::Dict{String,<:Any})
52 | bus_gens = Dict(bus["index"] => [] for (i,bus) in pm_data["bus"])
53 |
54 | for (i,gen) in pm_data["gen"]
55 | if gen["gen_status"] != 0
56 | push!(bus_gens[gen["gen_bus"]], i)
57 | end
58 | end
59 | for (i,gen) in pm_data["gen_nd"]
60 | if gen["gen_status"] != 0
61 | push!(bus_gens[gen["gen_bus"]], i)
62 | end
63 | end
64 | for (i,gen) in pm_data["gen_slack"]
65 | if gen["gen_status"] != 0
66 | push!(bus_gens[gen["gen_bus"]], i)
67 | end
68 | end
69 |
70 | slack_found = false
71 | for (i, bus) in pm_data["bus"]
72 | idx = bus["index"]
73 | if bus["bus_type"] == 1
74 | if length(bus_gens[idx]) != 0 # PQ
75 | #Memento.warn(_LOGGER, "active generators found at bus $(bus["bus_i"]), updating to bus type from $(bus["bus_type"]) to 2")
76 | #bus["bus_type"] = 2
77 | end
78 | elseif bus["bus_type"] == 2 # PV
79 | if length(bus_gens[idx]) == 0
80 | Memento.warn(_LOGGER, "no active generators found at bus $(bus["bus_i"]), updating to bus type from $(bus["bus_type"]) to 1")
81 | bus["bus_type"] = 1
82 | end
83 | elseif bus["bus_type"] == 3 # Slack
84 | if length(bus_gens[idx]) != 0
85 | slack_found = true
86 | else
87 | Memento.warn(_LOGGER, "no active generators found at bus $(bus["bus_i"]), updating to bus type from $(bus["bus_type"]) to 1")
88 | bus["bus_type"] = 1
89 | end
90 | elseif bus["bus_type"] == 4 # inactive bus
91 | # do nothing
92 | else # unknown bus type
93 | new_bus_type = 1
94 | if length(bus_gens[idx]) != 0
95 | new_bus_type = 2
96 | end
97 | Memento.warn(_LOGGER, "bus $(bus["bus_i"]) has an unrecongized bus_type $(bus["bus_type"]), updating to bus_type $(new_bus_type)")
98 | bus["bus_type"] = new_bus_type
99 | end
100 | end
101 |
102 | if !slack_found
103 | gen = _biggest_generator(pm_data["gen"])
104 | if length(gen) > 0
105 | gen_bus = gen["gen_bus"]
106 | ref_bus = pm_data["bus"]["$(gen_bus)"]
107 | ref_bus["bus_type"] = 3
108 | Memento.warn(_LOGGER, "no reference bus found, setting bus $(gen_bus) as reference based on generator $(gen["index"])")
109 | else
110 | Memento.error(_LOGGER, "no generators found in the given network data, correct_bus_types! requires at least one generator at the reference bus")
111 | end
112 | end
113 |
114 | end
115 |
--------------------------------------------------------------------------------
/edisgo/opf/eDisGo_OPF.jl/src/core/solution.jl:
--------------------------------------------------------------------------------
1 | function sol_component_value_radial(aim::AbstractPowerModel, n::Int, comp_name::Symbol, field_name_to::Symbol, comp_ids_to, variables)
2 | for (l, i, j) in comp_ids_to
3 | @assert !haskey(InfrastructureModels.sol(aim, pm_it_sym, n, comp_name, l), field_name_to)
4 | InfrastructureModels.sol(aim, pm_it_sym, n, comp_name, l)[field_name_to] = variables[(l, i, j)]
5 | end
6 | end
7 |
8 |
9 | function check_SOC_equality(result, data_edisgo)
10 | timesteps = keys(result["solution"]["nw"])
11 | branches = keys(data_edisgo["branch"])
12 | branches_wo_storage = [branch for branch in branches if !(data_edisgo["branch"][branch]["storage"])]
13 | branch_f_bus = Dict(k => string(data_edisgo["branch"][k]["f_bus"]) for k in branches_wo_storage)
14 | soc_eq_dict = Dict()
15 | soc_tight = true
16 | for t in timesteps
17 | eq_res = Dict(b => (result["solution"]["nw"][t]["branch"][b]["pf"]^2
18 | + result["solution"]["nw"][t]["branch"][b]["qf"]^2
19 | -result["solution"]["nw"][t]["branch"][b]["ccm"]*result["solution"]["nw"][t]["bus"][branch_f_bus[b]]["w"]) for b in branches_wo_storage)
20 | soc_eq_dict[t]= filter(((k,v),) -> v <-1e-1, eq_res)
21 | if length(keys(soc_eq_dict[t])) > 0
22 | soc_tight = false
23 | end
24 | end
25 | return soc_tight, soc_eq_dict
26 | end
27 |
--------------------------------------------------------------------------------
/edisgo/opf/eDisGo_OPF.jl/src/core/types.jl:
--------------------------------------------------------------------------------
1 | ""
2 |
3 | abstract type AbstractBFModelEdisgo <: AbstractBFQPModel end
4 |
5 | """
6 | Radial branch flow model (eDisGo implementation)
7 | Applicable to problem formulations with `_bf` in the name.
8 | """
9 | mutable struct BFPowerModelEdisgo <: AbstractBFModelEdisgo @pm_fields end
10 |
11 | abstract type AbstractSOCBFModelEdisgo <: AbstractBFModelEdisgo end
12 |
13 | """
14 | Second-order cone relaxation of radial branch flow model (eDisGo implementation).
15 | Applicable to problem formulations with `_bf` in the name.
16 | """
17 | mutable struct SOCBFPowerModelEdisgo <: AbstractSOCBFModelEdisgo @pm_fields end
18 |
19 |
20 | abstract type AbstractNCBFModelEdisgo <: AbstractBFModelEdisgo end
21 |
22 | """
23 | Non convex radial branch flow model (eDisGo implementation).
24 | Applicable to problem formulations with `_bf` in the name.
25 | """
26 | mutable struct NCBFPowerModelEdisgo <: AbstractNCBFModelEdisgo @pm_fields end
27 |
--------------------------------------------------------------------------------
/edisgo/opf/eDisGo_OPF.jl/src/eDisGo_OPF.jl:
--------------------------------------------------------------------------------
1 | module eDisGo_OPF
2 |
3 | using PowerModels
4 | using InfrastructureModels
5 | using Memento
6 | using JuMP
7 | using Ipopt
8 | using JSON
9 | using Compat
10 | using Gurobi
11 |
12 | const _pm_global_keys = Set(["time_series", "per_unit"])
13 | const pm_it_name = "pm"
14 | const pm_it_sym = Symbol(pm_it_name)
15 |
16 | # include functions extending PowerModels functions
17 | include("core/types.jl")
18 | include("core/base.jl")
19 | include("core/constraint.jl")
20 | include("core/constraint_template.jl")
21 | include("core/data.jl")
22 | include("core/objective.jl")
23 | include("core/solution.jl")
24 | include("core/variables.jl")
25 | include("form/bf.jl")
26 | include("prob/opf_bf.jl")
27 | include("io/common.jl")
28 | include("io/json.jl")
29 | #include("../test/opf_test_case.jl")
30 |
31 | # export new types of PowerModels
32 | export BFPowerModelEdisgo, SOCBFPowerModelEdisgo, NCBFPowerModelEdisgo
33 |
34 | end
35 |
--------------------------------------------------------------------------------
/edisgo/opf/eDisGo_OPF.jl/src/io/common.jl:
--------------------------------------------------------------------------------
1 | function correct_network_data!(data::Dict{String,<:Any})
2 | check_conductors(data)
3 | check_connectivity(data)
4 | check_status(data)
5 | # check_reference_bus(data)
6 | make_per_unit!(data)
7 |
8 | correct_transformer_parameters!(data)
9 | correct_voltage_angle_differences!(data)
10 | correct_thermal_limits!(data)
11 | correct_current_limits!(data)
12 | correct_branch_directions!(data)
13 |
14 | check_branch_loops(data)
15 | correct_dcline_limits!(data)
16 |
17 | # data_ep = _IM.ismultiinfrastructure(data) ? data["it"][pm_it_name] : data
18 |
19 | # if length(data_ep["gen"]) > 0 && any(gen["gen_status"] != 0 for (i, gen) in data_ep["gen"])
20 | # eDisGo_OPF.correct_bus_types!(data)
21 | # end
22 |
23 | check_voltage_setpoints(data)
24 | check_storage_parameters(data)
25 | check_switch_parameters(data)
26 |
27 | correct_cost_functions!(data)
28 |
29 | simplify_cost_terms!(data)
30 | end
31 |
--------------------------------------------------------------------------------
/edisgo/opf/eDisGo_OPF.jl/src/io/json.jl:
--------------------------------------------------------------------------------
1 | "Parses json from iostream or string"
2 | function parse_json(io::Union{IO,String}; kwargs...)::Dict{String,Any}
3 | pm_data = JSON.parse(io)
4 |
5 | PowerModels._jsonver2juliaver!(pm_data)
6 |
7 | if haskey(pm_data, "conductors")
8 | Memento.warn(_LOGGER, "The JSON data contains the conductor parameter, but only single conductors are supported. Consider using PowerModelsDistribution.")
9 | end
10 |
11 | if get(kwargs, :validate, true)
12 | eDisGo_OPF.correct_network_data!(pm_data)
13 | end
14 |
15 | return pm_data
16 | end
17 |
--------------------------------------------------------------------------------
/edisgo/opf/eDisGo_OPF.jl/src/prob/opf_bf.jl:
--------------------------------------------------------------------------------
1 | "Solve multinetwork branch flow OPF with multiple flexibilities"
2 | function solve_mn_opf_bf_flex(file, model_type::Type{T}, optimizer; kwargs...) where T <: AbstractBFModel
3 | return eDisGo_OPF.solve_model(file, model_type, optimizer, build_mn_opf_bf_flex; multinetwork=true, kwargs...)
4 | end
5 |
6 |
7 | "Build multinetwork branch flow OPF with multiple flexibilities"
8 | function build_mn_opf_bf_flex(pm::AbstractBFModelEdisgo)
9 | if PowerModels.ref(pm, 1, :opf_version) in(1, 3)
10 | eDisGo_OPF.variable_max_line_loading(pm, nw=1) # Eq. (3.41) (nur für Version 1 und 3)
11 | end
12 | for (n, network) in PowerModels.nws(pm)
13 | # VARIABLES
14 | if PowerModels.ref(pm, 1, :opf_version) in(1, 2, 3, 4)
15 | eDisGo_OPF.variable_branch_power_radial(pm, nw=n, bounded=false) # keine Begrenzung für Leistung auf Leitungen/Trafos (Strombegrenzung stattdessen)
16 | if PowerModels.ref(pm, 1, :opf_version) in(1, 3) # nur für Version 1 und 3 (ohne Netzrestriktionen)
17 | eDisGo_OPF.variable_branch_current(pm, nw=n, bounded=false) # keine Eq. (3.7)!
18 | eDisGo_OPF.variable_bus_voltage(pm, nw=n, bounded=false) # keine Eq. (3.8)!
19 | eDisGo_OPF.constraint_max_line_loading(pm, n) # Eq. (3.40)
20 | else # nur für Version 2 und 4 (mit Netzrestriktionen)
21 | eDisGo_OPF.variable_branch_current(pm, nw=n) # Eq. (3.7) und (3.7i)
22 | eDisGo_OPF.variable_gen_power_curt(pm, nw=n) # Eq. (3.44) für non-dispatchable Generators
23 | eDisGo_OPF.variable_slack_grid_restrictions(pm, nw=n) # Eq. (3.44)-(3.47)
24 | eDisGo_OPF.variable_bus_voltage(pm, nw=n) # Eq. (3.8)
25 | end
26 | eDisGo_OPF.variable_slack_heat_pump_storage(pm, nw=n) # Eq. (3.44)-(3.47)
27 | eDisGo_OPF.variable_battery_storage(pm, nw=n) # Eq. (3.11) und (3.12)
28 | eDisGo_OPF.variable_heat_storage(pm, nw=n) # Eq. (3.24)
29 | eDisGo_OPF.variable_heat_pump_power(pm, nw=n) # Eq. (3.20)
30 | eDisGo_OPF.variable_cp_power(pm, nw=n) # Eq. (3.27), (3.28)
31 | eDisGo_OPF.variable_dsm_storage_power(pm, nw=n) # Eq. (3.34), (3.35)
32 | eDisGo_OPF.variable_slack_gen(pm, nw=n) # keine Bounds für Slack Generator
33 |
34 | if PowerModels.ref(pm, 1, :opf_version) in(3, 4) # Nicht Teil der MA
35 | eDisGo_OPF.variable_slack_HV_requirements(pm, nw=n)
36 | if PowerModels.ref(pm, 1, :opf_version) in(3)
37 | eDisGo_OPF.variable_gen_power_curt(pm, nw=n)
38 | end
39 | for i in PowerModels.ids(pm, :HV_requirements, nw=n)
40 | eDisGo_OPF.constraint_HV_requirements(pm, i, n)
41 | end
42 | end
43 | else
44 | throw(ArgumentError("OPF version $(PowerModels.ref(pm, 1, :opf_version)) is not implemented! Choose between version 1 to 4."))
45 | end
46 |
47 | # CONSTRAINTS
48 | for i in PowerModels.ids(pm, :bus, nw=n)
49 | eDisGo_OPF.constraint_power_balance_bf(pm, i, nw=n) # Eq. (3.3ii), (3.4ii) für Version 1 und 3 bzw. (3.3iii), (3.4iii) für Version 2 und 4
50 | end
51 | for i in PowerModels.ids(pm, :branch, nw=n)
52 | eDisGo_OPF.constraint_voltage_magnitude_difference_radial(pm, i, nw=n) # Eq. (3.5)
53 | end
54 | eDisGo_OPF.constraint_model_current(pm, nw=n) # Eq. (3.6) bzw. (3.6i) (je nachdem ob nicht-konvex oder konvex gelöst wird) und (3.6ii)
55 |
56 |
57 | for i in PowerModels.ids(pm, :heatpumps, nw=n)
58 | eDisGo_OPF.constraint_hp_operation(pm, i, n) # Eq. (3.19)
59 | end
60 |
61 | end
62 |
63 | # CONSTRAINTS
64 | network_ids = sort(collect(PowerModels.nw_ids(pm)))
65 | for kind in ["storage", "heat_storage", "dsm"]
66 | n_1 = network_ids[1]
67 | for i in PowerModels.ids(pm, Symbol(kind), nw=n_1)
68 | eDisGo_OPF.constraint_store_state(pm, i, nw=n_1, kind=kind) # Eq. (3.9)+(3.10), (3.22)+(3.23), (3.32)+(3.33)
69 | end
70 |
71 | for n_2 in network_ids[2:end]
72 | for i in PowerModels.ids(pm, Symbol(kind), nw=n_2)
73 | eDisGo_OPF.constraint_store_state(pm, i, n_1, n_2, kind) # Eq. (3.10), (3.23), (3.33)
74 | end
75 | n_1 = n_2
76 | end
77 | end
78 |
79 | n_1 = network_ids[1]
80 |
81 | for i in PowerModels.ids(pm, :electromobility, nw=n_1)
82 | eta = PowerModels.ref(pm, 1, :electromobility)[i]["eta"]
83 | eDisGo_OPF.constraint_cp_state_initial(pm, n_1, i, eta) # Eq. (3.25)
84 | end
85 |
86 | for n_2 in network_ids[2:end]
87 | for i in PowerModels.ids(pm, :electromobility, nw=n_2)
88 | eta = PowerModels.ref(pm, 1, :electromobility)[i]["eta"]
89 | eDisGo_OPF.constraint_cp_state(pm, n_1, n_2, i, eta) # Eq. (3.26) (und (3.25) für letzten Zeitschritt)
90 | end
91 | n_1 = n_2
92 | end
93 |
94 | # OBJECTIVE FUNCTION
95 | if PowerModels.ref(pm, 1, :opf_version) == 1
96 | #eDisGo_OPF.objective_min_losses(pm)
97 | eDisGo_OPF.objective_min_line_loading_max(pm) # Eq. (3.2 ii)
98 | elseif (PowerModels.ref(pm, 1, :opf_version) == 3) # Nicht Teil der MA
99 | eDisGo_OPF.objective_min_line_loading_max_OG(pm)
100 | elseif PowerModels.ref(pm, 1, :opf_version) == 2
101 | eDisGo_OPF.objective_min_losses_slacks(pm) # Eq. (3.2 iii)
102 | elseif PowerModels.ref(pm, 1, :opf_version) == 4
103 | eDisGo_OPF.objective_min_losses_slacks_OG(pm) # Nicht Teil der MA
104 | end
105 | end
106 |
--------------------------------------------------------------------------------
/edisgo/opf/opf_solutions/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/edisgo/opf/opf_solutions/__init__.py
--------------------------------------------------------------------------------
/edisgo/opf/results/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/edisgo/opf/results/__init__.py
--------------------------------------------------------------------------------
/edisgo/tools/__init__.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from contextlib import contextmanager
4 |
5 | from sqlalchemy.orm import sessionmaker
6 |
7 | if "READTHEDOCS" not in os.environ:
8 | from egoio.tools.db import connection
9 |
10 | Session = sessionmaker(bind=connection(readonly=True))
11 |
12 |
13 | @contextmanager
14 | def session_scope():
15 | """Function to ensure that sessions are closed properly."""
16 | session = Session()
17 | try:
18 | yield session
19 | except Exception:
20 | session.rollback()
21 | raise
22 | finally:
23 | session.close()
24 |
--------------------------------------------------------------------------------
/edisgo/tools/networkx_helper.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from networkx import Graph
4 | from pandas import DataFrame
5 |
6 |
7 | def translate_df_to_graph(
8 | buses_df: DataFrame,
9 | lines_df: DataFrame,
10 | transformers_df: DataFrame | None = None,
11 | ) -> Graph:
12 | """
13 | Translate DataFrames to networkx Graph Object.
14 |
15 | Parameters
16 | ----------
17 | buses_df : :pandas:`pandas.DataFrame`
18 | Dataframe with all buses to use as Graph nodes. For more information about the
19 | Dataframe see :attr:`~.network.topology.Topology.buses_df`.
20 | lines_df : :pandas:`pandas.DataFrame`
21 | Dataframe with all lines to use as Graph branches. For more information about
22 | the Dataframe see :attr:`~.network.topology.Topology.lines_df`
23 | transformers_df : :pandas:`pandas.DataFrame`, optional
24 | Dataframe with all transformers to use as additional Graph nodes. For more
25 | information about the Dataframe see
26 | :attr:`~.network.topology.Topology.transformers_df`
27 |
28 | Returns
29 | -------
30 | :networkx:`networkx.Graph<>`
31 | Graph representation of the grid as networkx Ordered Graph,
32 | where lines are represented by edges in the graph, and buses and
33 | transformers are represented by nodes.
34 |
35 | """
36 | graph = Graph()
37 |
38 | # add nodes
39 | buses = [
40 | (bus_name, {"pos": (x, y)})
41 | for bus_name, x, y in buses_df[["x", "y"]].itertuples()
42 | ]
43 |
44 | graph.add_nodes_from(buses)
45 |
46 | # add branches
47 | branches = [
48 | (bus0, bus1, {"branch_name": line_name, "length": length})
49 | for line_name, bus0, bus1, length in lines_df[
50 | ["bus0", "bus1", "length"]
51 | ].itertuples()
52 | ]
53 |
54 | if transformers_df is not None:
55 | branches.extend(
56 | (bus0, bus1, {"branch_name": trafo_name, "length": 0})
57 | for trafo_name, bus0, bus1 in transformers_df[["bus0", "bus1"]].itertuples()
58 | )
59 |
60 | graph.add_edges_from(branches)
61 |
62 | return graph
63 |
--------------------------------------------------------------------------------
/examples/data/vg250.cpg:
--------------------------------------------------------------------------------
1 | ISO-8859-1
2 |
--------------------------------------------------------------------------------
/examples/data/vg250.dbf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/examples/data/vg250.dbf
--------------------------------------------------------------------------------
/examples/data/vg250.prj:
--------------------------------------------------------------------------------
1 | GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]]
2 |
--------------------------------------------------------------------------------
/examples/data/vg250.shp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/examples/data/vg250.shp
--------------------------------------------------------------------------------
/examples/data/vg250.shx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/examples/data/vg250.shx
--------------------------------------------------------------------------------
/rtd_requirements.txt:
--------------------------------------------------------------------------------
1 | dash < 2.9.0
2 | demandlib < 0.3.0
3 | egoio >= 0.4.7, < 0.5.0
4 | geopy >= 2.0.0, < 2.5.0
5 | jupyter_dash < 0.5.0
6 | matplotlib < 3.11.0
7 | multiprocess < 0.71.0
8 | networkx >= 2.5.0, < 3.5.0
9 | pandas >= 1.4.0, < 2.2.0
10 | plotly < 6.0
11 | pypower < 5.2.0
12 | pyproj >=3.0.0, < 3.8.0
13 | pypsa == 0.26.2
14 | pyyaml < 6.1.0
15 | saio < 0.3.0
16 | scikit-learn < 1.6
17 | sphinx < 8.3.0
18 | sphinx_rtd_theme >= 0.5.2, < 3.1.0
19 | sphinx-autodoc-typehints < 3.2.0
20 | sphinx-autoapi < 3.7.0
21 | sshtunnel < 0.5.0
22 | urllib3 < 2.5.0
23 | workalendar < 17.1.0
24 | astroid == 3.3.10
25 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | """Setup"""
2 |
3 | import os
4 | import sys
5 |
6 | from setuptools import find_packages, setup
7 |
8 | if sys.version_info[:2] < (3, 9):
9 | error = (
10 | "eDisGo requires Python 3.9 or later (%d.%d detected)." % sys.version_info[:2]
11 | )
12 | sys.stderr.write(error + "\n")
13 | sys.exit(1)
14 |
15 |
16 | def read(fname):
17 | """
18 | Read a text file.
19 |
20 | Parameters
21 | ----------
22 | fname : str or PurePath
23 | Path to file
24 |
25 | Returns
26 | -------
27 | str
28 | File content
29 |
30 | """
31 | return open(os.path.join(os.path.dirname(__file__), fname)).read()
32 |
33 |
34 | requirements = [
35 | "contextily < 1.7.0",
36 | "dash < 2.9.0",
37 | "demandlib < 0.3.0",
38 | "descartes < 1.2.0",
39 | "egoio >= 0.4.7, < 0.5.0",
40 | "geoalchemy2 < 0.7.0",
41 | "geopandas >= 0.12.0, < 1.1.0",
42 | "geopy >= 2.0.0, < 2.5.0",
43 | "jupyterlab < 4.5.0",
44 | "jupyter_dash < 0.5.0",
45 | "matplotlib >= 3.3.0, < 3.11.0",
46 | "multiprocess < 0.71.0",
47 | "networkx >= 2.5.0, < 3.5.0",
48 | # newer pandas versions don't work with specified sqlalchemy versions, but upgrading
49 | # sqlalchemy leads to new errors.. should be fixed at some point
50 | "numpy ==1.26.4",
51 | "pandas >= 1.4.0, < 2.2.0",
52 | "plotly < 6.0",
53 | "pydot < 4.1.0",
54 | "pygeos < 0.15.0",
55 | "pypower < 5.2.0",
56 | "pyproj >= 3.0.0, < 3.8.0",
57 | "pypsa == 0.26.2",
58 | "pyyaml < 6.1.0",
59 | "saio < 0.3.0",
60 | "scikit-learn < 1.3.0",
61 | "shapely >= 1.7.0, < 2.1.0",
62 | "sqlalchemy < 1.4.0",
63 | "sshtunnel < 0.5.0",
64 | "urllib3 < 2.5.0",
65 | "workalendar < 17.1.0",
66 | "astroid == 3.3.10",
67 | ]
68 |
69 | dev_requirements = [
70 | "black < 25.2.0",
71 | "flake8 < 7.3.0",
72 | "isort < 6.1.0",
73 | "pre-commit < 4.3.0",
74 | "pylint < 3.4.0",
75 | "pytest < 8.4.0",
76 | "pytest-notebook < 0.11.0",
77 | "pyupgrade < 3.20.0",
78 | "sphinx < 8.3.0",
79 | "sphinx_rtd_theme >=0.5.2, < 3.1.0",
80 | "sphinx-autodoc-typehints < 3.2.0",
81 | "sphinx-autoapi < 3.7.0",
82 | "astroid == 3.3.10",
83 | ]
84 |
85 | extras = {"dev": dev_requirements}
86 |
87 | setup(
88 | name="eDisGo",
89 | version="0.3.0dev",
90 | packages=find_packages(),
91 | url="https://github.com/openego/eDisGo",
92 | license="GNU Affero General Public License v3.0",
93 | author=(
94 | "birgits, AnyaHe, khelfen, mltja, gplssm, nesnoj, jaappedersen, Elias, "
95 | "boltbeard"
96 | ),
97 | author_email="anya.heider@rl-institut.de",
98 | description="A python package for distribution network analysis and optimization",
99 | long_description=read("README.md"),
100 | long_description_content_type="text/markdown",
101 | install_requires=requirements,
102 | extras_require=extras,
103 | package_data={
104 | "edisgo": [
105 | os.path.join("config", "*.cfg"),
106 | os.path.join("equipment", "*.csv"),
107 | ]
108 | },
109 | )
110 |
--------------------------------------------------------------------------------
/tests/conftest.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | import pytest
4 |
5 | from edisgo.io.db import engine
6 |
7 |
8 | def pytest_configure(config):
9 | # small self constructed ding0 grid with only 9 LV grids used for general testing
10 | pytest.ding0_test_network_path = os.path.join(
11 | os.path.realpath(os.path.dirname(__file__)), "data/ding0_test_network_1"
12 | )
13 | # real ding0 grid without georeference in LV used to test import of open_ego data
14 | # from oedb
15 | pytest.ding0_test_network_2_path = os.path.join(
16 | os.path.realpath(os.path.dirname(__file__)), "data/ding0_test_network_2"
17 | )
18 | # real ding0 grid from newer version of ding0 with georeferenced LV used to test
19 | # import of egon_data data
20 | pytest.ding0_test_network_3_path = os.path.join(
21 | os.path.realpath(os.path.dirname(__file__)), "data/ding0_test_network_3"
22 | )
23 |
24 | pytest.simbev_example_scenario_path = os.path.join(
25 | os.path.realpath(os.path.dirname(__file__)), "data/simbev_example_scenario"
26 | )
27 |
28 | pytest.tracbev_example_scenario_path = os.path.join(
29 | os.path.realpath(os.path.dirname(__file__)), "data/tracbev_example_scenario"
30 | )
31 |
32 | # pytest.egon_data_config_yml = os.path.join(
33 | # "path/to/ssh/config.yml",
34 | # )
35 |
36 | pytest.engine = engine()
37 |
38 | config.addinivalue_line("markers", "slow: mark test as slow to run")
39 | config.addinivalue_line("markers", "local: mark test as local to run")
40 |
41 | # if config.getoption("--runlocal"):
42 | # pytest.engine_local = engine(path=pytest.egon_data_config_yml, ssh=False)
43 |
44 |
45 | def pytest_addoption(parser):
46 | parser.addoption(
47 | "--runslow", action="store_true", default=False, help="run slow tests"
48 | )
49 | parser.addoption(
50 | "--runonlinux",
51 | action="store_true",
52 | default=False,
53 | help="run tests that only work on linux",
54 | )
55 | parser.addoption(
56 | "--runlocal",
57 | action="store_true",
58 | default=False,
59 | help="run tests that only work locally",
60 | )
61 |
62 |
63 | def pytest_collection_modifyitems(config, items):
64 | if not config.getoption("--runslow"):
65 | skip_slow = pytest.mark.skip(reason="need --runslow option to run")
66 | for item in items:
67 | if "slow" in item.keywords:
68 | item.add_marker(skip_slow)
69 | if not config.getoption("--runlocal"):
70 | skip_local = pytest.mark.skip(reason="need --runlocal option to run")
71 | for item in items:
72 | if "local" in item.keywords:
73 | item.add_marker(skip_local)
74 | if not config.getoption("--runonlinux"):
75 | skip_windows = pytest.mark.skip(reason="need --runonlinux option to run")
76 | for item in items:
77 | if "runonlinux" in item.keywords:
78 | item.add_marker(skip_windows)
79 |
--------------------------------------------------------------------------------
/tests/data/ding0_test_network_1/ding0_test_network_1.md:
--------------------------------------------------------------------------------
1 | Manually created test network, not created with ding0!
2 |
3 | ding0 mv_grid_id has no real meaning
4 |
--------------------------------------------------------------------------------
/tests/data/ding0_test_network_1/generators.csv:
--------------------------------------------------------------------------------
1 | name,bus,control,p_nom,type,weather_cell_id,subtype
2 | Generator_1,Bus_Generator_1,PQ,0.775,gas,,
3 | GeneratorFluctuating_2,Bus_GeneratorFluctuating_2,PQ,2.3,wind,1122074,wind_wind_onshore
4 | GeneratorFluctuating_3,Bus_GeneratorFluctuating_3,PQ,2.67,solar,1122075,solar_solar_ground_mounted
5 | GeneratorFluctuating_4,Bus_GeneratorFluctuating_4,PQ,1.93,solar,1122075,solar_solar
6 | GeneratorFluctuating_5,Bus_GeneratorFluctuating_5,PQ,2.3,wind,1122075,wind_wind_onshore
7 | GeneratorFluctuating_6,Bus_GeneratorFluctuating_6,PQ,3.05,wind,1122075,wind_wind_onshore
8 | GeneratorFluctuating_7,Bus_GeneratorFluctuating_7,PQ,3,wind,1122075,wind_wind_onshore
9 | GeneratorFluctuating_8,Bus_GeneratorFluctuating_8,PQ,3,wind,1122075,wind_wind_onshore
10 | GeneratorFluctuating_agg_28,BusBar_lac_1,PQ,3.05,wind,1122075,wind_wind_onshore
11 | GeneratorFluctuating_9,Bus_BranchTee_LVGrid_1_10,PQ,0.005,solar,1122075,solar_solar_roof_mounted
12 | GeneratorFluctuating_10,Bus_BranchTee_LVGrid_1_10,PQ,0.002,solar,1122075,solar_solar_roof_mounted
13 | GeneratorFluctuating_11,Bus_BranchTee_LVGrid_1_8,PQ,0.005,solar,1122075,solar_solar_roof_mounted
14 | GeneratorFluctuating_12,Bus_BranchTee_LVGrid_1_12,PQ,0.011,solar,1122075,solar_solar_roof_mounted
15 | GeneratorFluctuating_13,Bus_BranchTee_LVGrid_1_14,PQ,0.029,solar,1122075,solar_solar_roof_mounted
16 | GeneratorFluctuating_14,Bus_BranchTee_LVGrid_1_14,PQ,0.005,solar,1122075,solar_solar_roof_mounted
17 | GeneratorFluctuating_15,Bus_BranchTee_LVGrid_2_4,PQ,0.006,solar,1122075,solar_solar_roof_mounted
18 | GeneratorFluctuating_16,Bus_GeneratorFluctuating_16,PQ,0.03,solar,1122075,solar_solar_roof_mounted
19 | GeneratorFluctuating_17,Bus_BranchTee_LVGrid_4_2,PQ,0.055,solar,1122075,solar_solar_roof_mounted
20 | GeneratorFluctuating_18,Bus_BranchTee_LVGrid_4_2,PQ,0.01,solar,1122075,solar_solar_roof_mounted
21 | GeneratorFluctuating_19,Bus_GeneratorFluctuating_19,PQ,0.023,solar,1122075,solar_solar_roof_mounted
22 | GeneratorFluctuating_20,Bus_BranchTee_LVGrid_7_6,PQ,0.005,solar,1122075,solar_solar_roof_mounted
23 | GeneratorFluctuating_21,Bus_BranchTee_LVGrid_7_6,PQ,0.036,solar,1122075,solar_solar_roof_mounted
24 | GeneratorFluctuating_22,Bus_BranchTee_LVGrid_7_4,PQ,0.008,solar,1122075,solar_solar_roof_mounted
25 | GeneratorFluctuating_23,Bus_BranchTee_LVGrid_8_2,PQ,0.003,solar,1122075,solar_solar_roof_mounted
26 | GeneratorFluctuating_24,Bus_BranchTee_LVGrid_8_8,PQ,0.003,solar,1122075,solar_solar_roof_mounted
27 | GeneratorFluctuating_25,Bus_BranchTee_LVGrid_8_12,PQ,0.006,solar,1122075,solar_solar_roof_mounted
28 | GeneratorFluctuating_26,Bus_BranchTee_LVGrid_8_10,PQ,0.004,solar,1122075,solar_solar_roof_mounted
29 | GeneratorFluctuating_27,Bus_BranchTee_LVGrid_8_16,PQ,0.021,solar,1122075,solar_solar_roof_mounted
30 |
--------------------------------------------------------------------------------
/tests/data/ding0_test_network_1/loads.csv:
--------------------------------------------------------------------------------
1 | name,bus,peak_load,sector,annual_consumption
2 | Load_retail_MVGrid_1_Load_aggregated_retail_MVGrid_1_1,BusBar_lac_1,0.31,retail,1520
3 | Load_agricultural_LVGrid_1_1,Bus_BranchTee_LVGrid_1_2,0.0523,agricultural,238
4 | Load_agricultural_LVGrid_1_2,Bus_BranchTee_LVGrid_1_4,0.0523,agricultural,514
5 | Load_agricultural_LVGrid_1_3,Bus_BranchTee_LVGrid_1_6,0.0523,agricultural,664
6 | Load_residential_LVGrid_1_4,Bus_BranchTee_LVGrid_1_8,0.001397,residential,6.1
7 | Load_residential_LVGrid_1_5,Bus_BranchTee_LVGrid_1_10,0.001397,residential,6.1
8 | Load_residential_LVGrid_1_6,Bus_BranchTee_LVGrid_1_12,0.001397,residential,6.1
9 | Load_residential_LVGrid_1_7,Bus_BranchTee_LVGrid_1_14,0.001397,residential,6.1
10 | Load_residential_LVGrid_2_1,Bus_BranchTee_LVGrid_2_2,0.001048,residential,5.7
11 | Load_residential_LVGrid_2_2,Bus_BranchTee_LVGrid_2_4,0.001048,residential,5.7
12 | Load_agricultural_LVGrid_3_1,Bus_BranchTee_LVGrid_3_2,0.051,agricultural,50
13 | Load_residential_LVGrid_3_2,Bus_BranchTee_LVGrid_3_4,0.001209,residential,4.3
14 | Load_residential_LVGrid_3_3,Bus_BranchTee_LVGrid_3_6,0.001209,residential,4.3
15 | Load_residential_LVGrid_3_4,Bus_BranchTee_LVGrid_3_8,0.001209,residential,4.3
16 | Load_residential_LVGrid_4_1,Bus_BranchTee_LVGrid_4_2,0.001354,residential,6.5
17 | Load_industrial_LVGrid_5_1,Bus_BranchTee_LVGrid_5_2,0.07992,industrial,100
18 | Load_agricultural_LVGrid_5_2,Bus_BranchTee_LVGrid_5_4,0.06196,agricultural,450
19 | Load_residential_LVGrid_5_3,Bus_Load_residential_LVGrid_5_3,0.001354,residential,4.7
20 | Load_industrial_LVGrid_6_1,Bus_BranchTee_LVGrid_6_2,0.07992,industrial,580
21 | Load_agricultural_LVGrid_7_1,Bus_BranchTee_LVGrid_7_2,0.06196,agricultural,630
22 | Load_residential_LVGrid_7_2,Bus_BranchTee_LVGrid_7_4,0.001164,residential,5.8
23 | Load_residential_LVGrid_7_3,Bus_BranchTee_LVGrid_7_6,0.001164,residential,5.8
24 | Load_agricultural_LVGrid_8_1,Bus_BranchTee_LVGrid_8_2,0.0478,agricultural,86
25 | Load_residential_LVGrid_8_2,Bus_BranchTee_LVGrid_8_4,0.001222,residential,4.9
26 | Load_residential_LVGrid_8_3,Bus_BranchTee_LVGrid_8_6,0.001222,residential,4.9
27 | Load_residential_LVGrid_8_4,Bus_BranchTee_LVGrid_8_8,0.001222,residential,4.9
28 | Load_residential_LVGrid_8_5,Bus_BranchTee_LVGrid_8_10,0.001222,residential,4.9
29 | Load_residential_LVGrid_8_6,Bus_BranchTee_LVGrid_8_12,0.001222,residential,4.9
30 | Load_residential_LVGrid_8_7,Bus_BranchTee_LVGrid_8_14,0.001222,residential,4.9
31 | Load_residential_LVGrid_8_8,Bus_BranchTee_LVGrid_8_16,0.001222,residential,4.9
32 | Load_residential_LVGrid_8_9,Bus_BranchTee_LVGrid_8_18,0.001222,residential,4.9
33 | Load_residential_LVGrid_8_10,Bus_BranchTee_LVGrid_8_20,0.001222,residential,4.9
34 | Load_residential_LVGrid_8_11,Bus_BranchTee_LVGrid_8_22,0.001222,residential,4.9
35 | Load_residential_LVGrid_8_12,Bus_BranchTee_LVGrid_8_24,0.001222,residential,4.9
36 | Load_residential_LVGrid_8_13,Bus_BranchTee_LVGrid_8_26,0.001222,residential,4.9
37 | Load_residential_LVGrid_8_14,Bus_BranchTee_LVGrid_8_28,0.001222,residential,4.9
38 | Load_agricultural_LVGrid_9_1,Bus_BranchTee_LVGrid_9_2,0.0478,agricultural,279
39 | Load_residential_LVGrid_9_2,Bus_BranchTee_LVGrid_9_4,0.001222,residential,4.9
40 | Load_residential_LVGrid_9_3,Bus_BranchTee_LVGrid_9_6,0.001222,residential,4.9
41 | Load_residential_LVGrid_9_4,Bus_BranchTee_LVGrid_9_8,0.001222,residential,4.9
42 | Load_residential_LVGrid_9_5,Bus_BranchTee_LVGrid_9_10,0.001222,residential,4.9
43 | Load_residential_LVGrid_9_6,Bus_BranchTee_LVGrid_9_12,0.001222,residential,4.9
44 | Load_residential_LVGrid_9_7,Bus_BranchTee_LVGrid_9_14,0.001222,residential,4.9
45 | Load_residential_LVGrid_9_8,Bus_BranchTee_LVGrid_9_16,0.001222,residential,4.9
46 | Load_residential_LVGrid_9_9,Bus_BranchTee_LVGrid_9_18,0.001222,residential,4.9
47 | Load_residential_LVGrid_9_10,Bus_BranchTee_LVGrid_9_20,0.001222,residential,4.9
48 | Load_residential_LVGrid_9_11,Bus_BranchTee_LVGrid_9_22,0.001222,residential,4.9
49 | Load_residential_LVGrid_9_12,Bus_BranchTee_LVGrid_9_24,0.001222,residential,4.9
50 | Load_residential_LVGrid_9_13,Bus_BranchTee_LVGrid_9_26,0.001222,residential,4.9
51 | Load_retail_LVGrid_9_14,Bus_BranchTee_LVGrid_9_28,0.001222,retail,143
52 |
--------------------------------------------------------------------------------
/tests/data/ding0_test_network_1/storage_units.csv:
--------------------------------------------------------------------------------
1 | name,bus,control,p_nom,capacity,efficiency_store,efficiency_dispatch
2 | Storage_1,Bus_MVStation_1,PQ,0.4,0.4,0.9,0.9
3 |
--------------------------------------------------------------------------------
/tests/data/ding0_test_network_1/switches.csv:
--------------------------------------------------------------------------------
1 | name,bus_closed,bus_open,branch,type_info
2 | circuit_breaker_1,BusBar_MVGrid_1_LVGrid_4_MV,virtual_BusBar_MVGrid_1_LVGrid_4_MV,Line_10031,Switch Disconnector
3 | circuit_breaker_2,BusBar_MVGrid_1_LVGrid_9_MV,virtual_BusBar_MVGrid_1_LVGrid_9_MV,Line_10016,Switch Disconnector
4 |
--------------------------------------------------------------------------------
/tests/data/ding0_test_network_1/transformers.csv:
--------------------------------------------------------------------------------
1 | name,bus0,bus1,x,r,s_nom,type_info
2 | LVStation_1_transformer_1,BusBar_MVGrid_1_LVGrid_1_MV,BusBar_MVGrid_1_LVGrid_1_LV,0.016,0.00588,0.16,160 kVA
3 | LVStation_2_transformer_1,BusBar_MVGrid_1_LVGrid_2_MV,BusBar_MVGrid_1_LVGrid_2_LV,0.0246,0.0098,0.05,50 kVA
4 | LVStation_3_transformer_1,BusBar_MVGrid_1_LVGrid_3_MV,BusBar_MVGrid_1_LVGrid_3_LV,0.016,0.007,0.1,100 kVA
5 | LVStation_4_transformer_1,BusBar_MVGrid_1_LVGrid_4_MV,BusBar_MVGrid_1_LVGrid_4_LV,0.0246,0.0098,0.04,40 kVA
6 | LVStation_4_transformer_2,BusBar_MVGrid_1_LVGrid_4_MV,BusBar_MVGrid_1_LVGrid_4_LV,0.0246,0.0098,0.01,10 kVA
7 | LVStation_5_transformer_1,BusBar_MVGrid_1_LVGrid_5_MV,BusBar_MVGrid_1_LVGrid_5_LV,0.016,0.007,0.1,100 kVA
8 | LVStation_6_transformer_1,BusBar_MVGrid_1_LVGrid_6_LV,BusBar_MVGrid_1_LVGrid_6_MV,0.0246,0.0098,0.05,50 kVA
9 | LVStation_7_transformer_1,BusBar_MVGrid_1_LVGrid_7_MV,BusBar_MVGrid_1_LVGrid_7_LV,0.016,0.007,0.1,100 kVA
10 | LVStation_8_transformer_1,BusBar_MVGrid_1_LVGrid_8_MV,BusBar_MVGrid_1_LVGrid_8_LV,0.016,0.007,0.1,100 kVA
11 | LVStation_9_transformer_1,BusBar_MVGrid_1_LVGrid_9_MV,BusBar_MVGrid_1_LVGrid_9_LV,0.016,0.007,0.1,100 kVA
12 | Transformer_lv_load_area_1_1,Bus_MVStation_1,BusBar_lac_1,0.059074106002546,0.0105,1,1.0 MVA 20/0.4 kV
13 | Transformer_lv_load_area_1_2,Bus_MVStation_1,BusBar_lac_1,0.059074106002546,0.0105,1,1.0 MVA 20/0.4 kV
14 | Transformer_lv_load_area_1_3,Bus_MVStation_1,BusBar_lac_1,0.059074106002546,0.0105,1,1.0 MVA 20/0.4 kV
15 | Transformer_lv_load_area_1_4,Bus_MVStation_1,BusBar_lac_1,0.059074106002546,0.0105,1,1.0 MVA 20/0.4 kV
16 |
--------------------------------------------------------------------------------
/tests/data/ding0_test_network_1/transformers_hvmv.csv:
--------------------------------------------------------------------------------
1 | name,bus0,bus1,x,r,s_nom,type_info
2 | MVStation_1_transformer_1,Bus_primary_MVStation_1,Bus_MVStation_1,,,40,40 MVA 110/20 kV
3 |
--------------------------------------------------------------------------------
/tests/data/ding0_test_network_2/Ding0_20210416184606.meta:
--------------------------------------------------------------------------------
1 | {"version": "v0.1.9-217-g919ef2c\n", "mv_grid_districts": [2095], "database_tables": {"mv_grid_districts": "EgoDpMvGriddistrict", "lv_load_areas": "EgoDpLoadarea", "lv_grid_district": "EgoDpLvGriddistrict", "mv_stations": "EgoDpHvmvSubstation", "lv_stations": "EgoDpMvlvSubstation", "re_generators": "t_ego_dp_res_powerplant_sq_mview", "conv_generators": "t_ego_dp_conv_powerplant_sq_mview", "version": "v0.4.5"}, "data_version": "v0.4.5", "assumptions": {"load_density_threshold": "1", "voltage_per_km_threshold": "15", "load_factor_mv_trans_lc_normal": "0.6", "load_factor_mv_line_lc_normal": "0.6", "load_factor_mv_cable_lc_normal": "0.6", "load_factor_mv_trans_lc_malfunc": "1.0", "load_factor_mv_line_lc_malfunc": "1.0", "load_factor_mv_cable_lc_malfunc": "1.0", "load_factor_mv_trans_fc_normal": "1.0", "load_factor_mv_line_fc_normal": "1.0", "load_factor_mv_cable_fc_normal": "1.0", "load_factor_lv_trans_lc_normal": "1.0", "load_factor_lv_cable_lc_normal": "1.0", "load_factor_lv_trans_fc_normal": "1.0", "load_factor_lv_cable_fc_normal": "1.0", "cos_phi_load": "0.97", "cos_phi_load_mode": "inductive", "cos_phi_gen": "1", "cos_phi_gen_mode": "capacitive", "frequency": "50", "lv_nominal_voltage": "400", "apartment_house_branch_ratio": "1.5", "population_per_apartment": "2.3", "branch_line_length_retail_industrial": "400", "branch_line_length_agricultural": "800", "max_lv_branch_line": "290", "lv_ria_branch_connection_distance": "30", "branch_detour_factor": "1.3", "load_in_generation_case": "0", "generation_in_load_case": "0", "lv_max_v_level_lc_diff_normal": "0.05", "lv_max_v_level_fc_diff_normal": "0.03", "load_area_sat_load_threshold": "100", "load_area_sat_string_load_threshold": "1000", "load_area_sat_conn_dist_weight": "1", "load_area_sat_string_length_threshold": "2000", "load_area_sat_conn_dist_ring_mod": "100", "load_area_stat_conn_dist_ring_mod": "300", "load_area_sat_buffer_radius": "2000", "load_area_sat_buffer_radius_inc": "1000", "generator_buffer_radius": "2000", "generator_buffer_radius_inc": "1000", "operator_diff_round_digits": "3", "conn_diff_tolerance": "0.0001", "load_area_threshold": "1", "load_area_count_per_ring": "20", "max_half_ring_length": "28", "mv_half_ring_count_max": "8", "mv_station_v_level_operation": "1.0", "mv_max_v_level_lc_diff_normal": "0.05", "mv_max_v_level_fc_diff_normal": "0.02", "mv_max_v_level_lc_diff_malfunc": "0.10"}, "run_id": "20210416184606"}
2 |
--------------------------------------------------------------------------------
/tests/data/ding0_test_network_2/network.csv:
--------------------------------------------------------------------------------
1 | name,srid,mv_grid_district_geom,mv_grid_district_population
2 | 2095,4326,"MULTIPOLYGON (((6.22171915597056 50.7000442498141, 6.21836845956992 50.7471015719592, 6.33629192568964 50.7650555050617, 6.34759596583486 50.7571800281125, 6.34568089681317 50.756444435602, 6.34226797371834 50.7552653528853, 6.34236507457769 50.754206555517, 6.34280029053606 50.7528165218547, 6.34386049608337 50.7515992884819, 6.34389812234061 50.7505746000382, 6.34265545323108 50.749410318405, 6.34066963834987 50.7479524681052, 6.33863180564131 50.7469788737339, 6.33853794135836 50.7460040011331, 6.33623714292214 50.7436811557718, 6.33534293396888 50.742419868912, 6.33223814184308 50.7405843171146, 6.33087299815527 50.7397219620257, 6.32955821220107 50.7391221653932, 6.32859793103724 50.7385246448353, 6.32750737031633 50.7374190170411, 6.32617005920515 50.733497798846, 6.32609105882311 50.731254507339, 6.32428276996426 50.7264723230418, 6.31945324940308 50.7202617686807, 6.31792977400304 50.7190792064936, 6.31595587005689 50.7167753238285, 6.31497642472233 50.714809181416, 6.3136392509724 50.7127055943527, 6.31277311835504 50.7107430518677, 6.31087482519684 50.7076675485333, 6.30957345348617 50.7049351006726, 6.30826013412194 50.7027152063505, 6.31039032768445 50.7023064921887, 6.31234093605401 50.7014780266615, 6.31238476903152 50.7014614313672, 6.31436570778371 50.700426922247, 6.31285536491118 50.6904524332909, 6.30979284499256 50.6899313850493, 6.30173929856764 50.6885481498806, 6.28616682696403 50.6863821536181, 6.27028771974073 50.6848790430016, 6.27270468868398 50.6943887248798, 6.27269055180282 50.6943882674042, 6.27143814093219 50.6949866929821, 6.25673640983272 50.7019434451649, 6.25672227080525 50.7019429857195, 6.23853436773398 50.7054723497745, 6.22171915597056 50.7000442498141)))",0
3 |
--------------------------------------------------------------------------------
/tests/data/ding0_test_network_2/switches.csv:
--------------------------------------------------------------------------------
1 | name,bus_closed,bus_open,branch,type_info
2 | circuit_breaker_1,BusBar_mvgd_2095_lvgd_500742_MV,virtual_BusBar_mvgd_2095_lvgd_500742_MV,Branch_LVStation_mvgd_2095_lvgd_170174_LVStation_mvgd_2095_lvgd_500742,Switch Disconnector
3 | circuit_breaker_2,BusBar_mvgd_2095_lvgd_136246_MV,virtual_BusBar_mvgd_2095_lvgd_136246_MV,Branch_LVStation_mvgd_2095_lvgd_136246_MVCableDist_mvgd_2095_2,Switch Disconnector
4 |
--------------------------------------------------------------------------------
/tests/data/ding0_test_network_2/transformers_hvmv.csv:
--------------------------------------------------------------------------------
1 | name,bus0,bus1,s_nom,r,x,type,type_info
2 | Transformer_mv_grid_2095_1,Busbar_mvgd_2095_HV,Busbar_mvgd_2095_MV,25.0,,,25 MVA 110/10 kV,25 MVA 110/10 kV
3 | Transformer_mv_grid_2095_2,Busbar_mvgd_2095_HV,Busbar_mvgd_2095_MV,25.0,,,25 MVA 110/10 kV,25 MVA 110/10 kV
4 |
--------------------------------------------------------------------------------
/tests/data/ding0_test_network_3/switches.csv:
--------------------------------------------------------------------------------
1 | name,bus_closed,bus_open,branch,type_info
2 | circuit_breaker_1,BusBar_mvgd_33535_lvgd_1166910000_MV,virtual_BusBar_mvgd_33535_lvgd_1166910000_MV,Branch_LVStation_mvgd_33535_lvgd_1166910000_MVCableDist_mvgd_33535_18,Switch Disconnector
3 | circuit_breaker_2,BusBar_mvgd_33535_lvgd_1164120007_MV,virtual_BusBar_mvgd_33535_lvgd_1164120007_MV,Branch_LVStation_mvgd_33535_lvgd_1164120007_MVCableDist_mvgd_33535_1,Switch Disconnector
4 | circuit_breaker_3,BusBar_mvgd_33535_lvgd_1172800000_MV,virtual_BusBar_mvgd_33535_lvgd_1172800000_MV,Branch_LVStation_mvgd_33535_lvgd_1172800000_MVCableDist_mvgd_33535_32,Switch Disconnector
5 |
--------------------------------------------------------------------------------
/tests/data/ding0_test_network_3/transformers_hvmv.csv:
--------------------------------------------------------------------------------
1 | name,bus0,bus1,s_nom,r,x,type,type_info
2 | Transformer_mv_grid_33535_1,Busbar_mvgd_33535_HV,Busbar_mvgd_33535_MV,40.0,,,40 MVA 110/20 kV,40 MVA 110/20 kV
3 | Transformer_mv_grid_33535_2,Busbar_mvgd_33535_HV,Busbar_mvgd_33535_MV,40.0,,,40 MVA 110/20 kV,40 MVA 110/20 kV
4 |
--------------------------------------------------------------------------------
/tests/data/simbev_example_scenario/5334032/bev_luxury_00000_110kWh_SR_Mitte_events.csv:
--------------------------------------------------------------------------------
1 | ,location,use_case,nominal_charging_capacity_kW,grid_charging_capacity_kW,battery_charging_capacity_kW,soc_start,soc_end,chargingdemand_kWh,park_time_timesteps,park_start_timesteps,park_end_timesteps,drive_start_timesteps,drive_end_timesteps,consumption_kWh
2 | 0,5_leisure,public,22.0,24.4444,22.0,0.9907,0.9907,0.0,0,0,41,0,0,0.0
3 | 1,driving,,0.0,0.0,0.0,0.9907,0.9495,0.0,0,0,0,42,46,4.5262
4 | 2,6_home,home,0.0,0.0,0.0,0.9495,0.9495,0.0,0,47,98,0,0,0.0
5 | 3,driving,,0.0,0.0,0.0,0.9495,0.867,0.0,0,0,0,99,137,9.0797
6 | 4,3_shopping,public,0.0,0.0,0.0,0.867,0.867,0.0,0,138,140,0,0,0.0
7 | 5,driving,,0.0,0.0,0.0,0.867,0.8392,0.0,0,0,0,141,143,3.0568
8 | 6,5_leisure,public,22.0,24.4444,22.0,0.8392,0.8392,0.0,0,144,153,0,0,0.0
9 | 7,driving,,0.0,0.0,0.0,0.8392,0.8218,0.0,0,0,0,154,163,1.9136
10 | 8,4_private/ridesharing,public,0.0,0.0,0.0,0.8218,0.8218,0.0,0,164,168,0,0,0.0
11 | 9,driving,,0.0,0.0,0.0,0.8218,0.8154,0.0,0,0,0,169,170,0.7081
12 | 10,3_shopping,public,0.0,0.0,0.0,0.8154,0.8154,0.0,0,171,174,0,0,0.0
13 | 11,driving,,0.0,0.0,0.0,0.8154,0.792,0.0,0,0,0,175,180,2.5694
14 | 12,6_home,home,0.0,0.0,0.0,0.792,0.792,0.0,0,181,247,0,0,0.0
15 | 13,driving,,0.0,0.0,0.0,0.792,0.7879,0.0,0,0,0,248,250,0.4465
16 | 14,3_shopping,public,11.0,12.2222,11.0,0.7879,0.7879,0.0,0,251,254,0,0,0.0
17 | 15,driving,,0.0,0.0,0.0,0.7879,0.7632,0.0,0,0,0,255,258,2.7199
18 | 16,6_home,home,0.0,0.0,0.0,0.7632,0.7632,0.0,0,259,343,0,0,0.0
19 | 17,driving,,0.0,0.0,0.0,0.7632,0.7453,0.0,0,0,0,344,345,1.972
20 | 18,0_work,work,0.0,0.0,0.0,0.7453,0.7453,0.0,0,346,390,0,0,0.0
21 | 19,driving,,0.0,0.0,0.0,0.7453,0.5423,0.0,0,0,0,391,424,22.3323
22 | 20,1_business,public,0.0,0.0,0.0,0.5423,0.5423,0.0,0,425,440,0,0,0.0
23 | 21,driving,,0.0,0.0,0.0,0.5423,0.5292,0.0,0,0,0,441,444,1.4357
24 | 22,4_private/ridesharing,public,0.0,0.0,0.0,0.5292,0.5292,0.0,0,445,448,0,0,0.0
25 | 23,driving,,0.0,0.0,0.0,0.5292,0.4867,0.0,0,0,0,449,451,4.6767
26 | 24,6_home,home,0.0,0.0,0.0,0.4867,0.4867,0.0,0,452,494,0,0,0.0
27 | 25,driving,,0.0,0.0,0.0,0.4867,0.4067,0.0,0,0,0,495,516,8.8008
28 | 26,0_work,work,0.0,0.0,0.0,0.4067,0.4067,0.0,0,517,530,0,0,0.0
29 | 27,driving,,0.0,0.0,0.0,0.4067,0.3874,0.0,0,0,0,531,533,2.1178
30 | 28,6_home,home,0.0,0.0,0.0,0.3874,0.3874,0.0,0,534,618,0,0,0.0
31 | 29,driving,,0.0,0.0,0.0,0.3874,0.3671,0.0,0,0,0,619,625,2.2322
32 | 30,4_private/ridesharing,public,0.0,0.0,0.0,0.3671,0.3671,0.0,0,626,629,0,0,0.0
33 | 31,driving,,0.0,0.0,0.0,0.3671,0.3552,0.0,0,0,0,630,632,1.3185
34 | 32,3_shopping,public,0.0,0.0,0.0,0.3552,0.3552,0.0,0,633,634,0,0,0.0
35 | 33,driving,,0.0,0.0,0.0,0.3552,0.3458,0.0,0,0,0,635,636,1.0259
36 | 34,5_leisure,public,0.0,0.0,0.0,0.3458,0.3458,0.0,0,637,642,0,0,0.0
37 | 35,driving,,0.0,0.0,0.0,0.3458,0.3266,0.0,0,0,0,643,648,2.1178
38 | 36,6_home,home,0.0,0.0,0.0,0.3266,0.3266,0.0,0,649,672,0,0,0.0
39 |
--------------------------------------------------------------------------------
/tests/data/simbev_example_scenario/5334032/bev_luxury_00001_110kWh_SR_Mitte_events.csv:
--------------------------------------------------------------------------------
1 | ,location,use_case,nominal_charging_capacity_kW,grid_charging_capacity_kW,battery_charging_capacity_kW,soc_start,soc_end,chargingdemand_kWh,park_time_timesteps,park_start_timesteps,park_end_timesteps,drive_start_timesteps,drive_end_timesteps,consumption_kWh
2 | 0,6_home,home,0.0,0.0,0.0,0.8995,0.8995,0.0,0,0,32,0,0,0.0
3 | 1,driving,,0.0,0.0,0.0,0.8995,0.8946,0.0,0,0,0,33,39,0.5337
4 | 2,3_shopping,public,0.0,0.0,0.0,0.8946,0.8946,0.0,0,40,106,0,0,0.0
5 | 3,driving,,0.0,0.0,0.0,0.8946,0.8874,0.0,0,0,0,107,139,0.7986
6 | 4,4_private/ridesharing,public,0.0,0.0,0.0,0.8874,0.8874,0.0,0,140,146,0,0,0.0
7 | 5,driving,,0.0,0.0,0.0,0.8874,0.8818,0.0,0,0,0,147,148,0.6126
8 | 6,6_home,home,0.0,0.0,0.0,0.8818,0.8818,0.0,0,149,182,0,0,0.0
9 | 7,driving,,0.0,0.0,0.0,0.8818,0.8689,0.0,0,0,0,183,217,1.4146
10 | 8,0_work,work,50.0,55.5556,50.0,0.8689,1.0,14.4159,15,218,232,0,0,0.0
11 | 9,driving,,0.0,0.0,0.0,1.0,0.9814,0.0,0,0,0,233,234,2.0414
12 | 10,5_leisure,public,0.0,0.0,0.0,0.9814,0.9814,0.0,0,235,240,0,0,0.0
13 | 11,driving,,0.0,0.0,0.0,0.9814,0.9622,0.0,0,0,0,241,243,2.1178
14 | 12,6_home,home,0.0,0.0,0.0,0.9622,0.9622,0.0,0,244,259,0,0,0.0
15 | 13,driving,,0.0,0.0,0.0,0.9622,0.9376,0.0,0,0,0,260,264,2.7101
16 | 14,4_private/ridesharing,public,50.0,55.5556,50.0,0.9376,0.9376,0.0,0,265,290,0,0,0.0
17 | 15,driving,,0.0,0.0,0.0,0.9376,0.8677,0.0,0,0,0,291,318,7.6859
18 | 16,0_work,work,50.0,55.5556,50.0,0.8677,1.0,14.5552,34,319,352,0,0,0.0
19 | 17,driving,,0.0,0.0,0.0,1.0,0.9845,0.0,0,0,0,353,354,1.7029
20 | 18,5_leisure,public,22.0,24.4444,22.0,0.9845,0.9845,0.0,0,355,441,0,0,0.0
21 | 19,driving,,0.0,0.0,0.0,0.9845,0.8147,0.0,0,0,0,442,454,18.6755
22 | 20,6_home,home,0.0,0.0,0.0,0.8147,0.8147,0.0,0,455,535,0,0,0.0
23 | 21,driving,,0.0,0.0,0.0,0.8147,0.7504,0.0,0,0,0,536,540,7.074
24 | 22,3_shopping,public,22.0,24.4444,22.0,0.7504,0.7504,0.0,0,541,543,0,0,0.0
25 | 23,driving,,0.0,0.0,0.0,0.7504,0.6628,0.0,0,0,0,544,553,9.644
26 | 24,6_home,home,0.0,0.0,0.0,0.6628,0.6628,0.0,0,554,622,0,0,0.0
27 | 25,driving,,0.0,0.0,0.0,0.6628,0.6571,0.0,0,0,0,623,625,0.6209
28 | 26,3_shopping,public,50.0,55.5556,50.0,0.6571,0.998,37.5,3,626,628,0,0,0.0
29 | 27,driving,,0.0,0.0,0.0,0.998,0.9651,0.0,0,0,0,629,639,3.6231
30 | 28,6_home,home,0.0,0.0,0.0,0.9651,0.9651,0.0,0,640,672,0,0,0.0
31 |
--------------------------------------------------------------------------------
/tests/data/simbev_example_scenario/5334032/bev_luxury_00002_110kWh_SR_Mitte_events.csv:
--------------------------------------------------------------------------------
1 | ,location,use_case,nominal_charging_capacity_kW,grid_charging_capacity_kW,battery_charging_capacity_kW,soc_start,soc_end,chargingdemand_kWh,park_time_timesteps,park_start_timesteps,park_end_timesteps,drive_start_timesteps,drive_end_timesteps,consumption_kWh
2 | 0,6_home,home,11.0,12.2222,11.0,0.8557,1.0,10.3757,88,0,88,0,0,0.0
3 | 1,driving,,0.0,0.0,0.0,1.0,0.9927,0.0,0,0,0,89,132,0.7986
4 | 2,4_private/ridesharing,public,0.0,0.0,0.0,0.9927,0.9927,0.0,0,133,136,0,0,0.0
5 | 3,driving,,0.0,0.0,0.0,0.9927,0.9749,0.0,0,0,0,137,138,1.9673
6 | 4,6_home,home,11.0,12.2222,11.0,0.9749,0.9749,0.0,0,139,230,0,0,0.0
7 | 5,driving,,0.0,0.0,0.0,0.9749,0.9708,0.0,0,0,0,231,234,0.4465
8 | 6,3_shopping,public,50.0,55.5556,50.0,0.9708,0.9708,0.0,0,235,237,0,0,0.0
9 | 7,driving,,0.0,0.0,0.0,0.9708,0.9621,0.0,0,0,0,238,241,0.9579
10 | 8,4_private/ridesharing,public,0.0,0.0,0.0,0.9621,0.9621,0.0,0,242,243,0,0,0.0
11 | 9,driving,,0.0,0.0,0.0,0.9621,0.958,0.0,0,0,0,244,245,0.4465
12 | 10,3_shopping,public,22.0,24.4444,22.0,0.958,0.958,0.0,0,246,249,0,0,0.0
13 | 11,driving,,0.0,0.0,0.0,0.958,0.9018,0.0,0,0,0,250,256,6.182
14 | 12,6_home,home,11.0,12.2222,11.0,0.9018,1.0,10.7987,49,257,305,0,0,0.0
15 | 13,driving,,0.0,0.0,0.0,1.0,0.9504,0.0,0,0,0,306,316,5.4561
16 | 14,0_work,work,0.0,0.0,0.0,0.9504,0.9504,0.0,0,317,344,0,0,0.0
17 | 15,driving,,0.0,0.0,0.0,0.9504,0.9421,0.0,0,0,0,345,349,0.9136
18 | 16,6_home,home,11.0,12.2222,11.0,0.9421,1.0,6.3697,3,350,352,0,0,0.0
19 | 17,driving,,0.0,0.0,0.0,1.0,0.9783,0.0,0,0,0,353,354,2.3915
20 | 18,4_private/ridesharing,public,0.0,0.0,0.0,0.9783,0.9783,0.0,0,355,356,0,0,0.0
21 | 19,driving,,0.0,0.0,0.0,0.9783,0.9275,0.0,0,0,0,357,367,5.5799
22 | 20,6_home,home,11.0,12.2222,11.0,0.9275,1.0,7.9714,66,368,433,0,0,0.0
23 | 21,driving,,0.0,0.0,0.0,1.0,0.9623,0.0,0,0,0,434,436,4.1437
24 | 22,4_private/ridesharing,public,0.0,0.0,0.0,0.9623,0.9623,0.0,0,437,451,0,0,0.0
25 | 23,driving,,0.0,0.0,0.0,0.9623,0.8938,0.0,0,0,0,452,455,7.5367
26 | 24,6_home,home,11.0,12.2222,11.0,0.8938,1.0,11.6804,46,456,501,0,0,0.0
27 | 25,driving,,0.0,0.0,0.0,1.0,0.9593,0.0,0,0,0,502,510,4.4806
28 | 26,0_work,work,0.0,0.0,0.0,0.9593,0.9593,0.0,0,511,515,0,0,0.0
29 | 27,driving,,0.0,0.0,0.0,0.9593,0.9497,0.0,0,0,0,516,519,1.0569
30 | 28,3_shopping,public,50.0,55.5556,50.0,0.9497,0.9497,0.0,0,520,524,0,0,0.0
31 | 29,driving,,0.0,0.0,0.0,0.9497,0.9359,0.0,0,0,0,525,526,1.5157
32 | 30,6_home,home,11.0,12.2222,11.0,0.9359,1.0,7.0532,64,527,590,0,0,0.0
33 | 31,driving,,0.0,0.0,0.0,1.0,0.9504,0.0,0,0,0,591,606,5.4561
34 | 32,0_work,work,0.0,0.0,0.0,0.9504,0.9504,0.0,0,607,646,0,0,0.0
35 | 33,driving,,0.0,0.0,0.0,0.9504,0.3072,0.0,0,0,0,647,667,70.7569
36 | 34,6_home,home,11.0,12.2222,11.0,0.3072,0.3072,0.0,20,668,672,0,0,0.0
37 |
--------------------------------------------------------------------------------
/tests/data/simbev_example_scenario/5334032/bev_medium_00000_90kWh_SR_Mitte_events.csv:
--------------------------------------------------------------------------------
1 | ,location,use_case,nominal_charging_capacity_kW,grid_charging_capacity_kW,battery_charging_capacity_kW,soc_start,soc_end,chargingdemand_kWh,park_time_timesteps,park_start_timesteps,park_end_timesteps,drive_start_timesteps,drive_end_timesteps,consumption_kWh
2 | 0,6_home,home,0.0,0.0,0.0,0.8263,0.8263,0.0,0,0,55,0,0,0.0
3 | 1,driving,,0.0,0.0,0.0,0.8263,0.8197,0.0,0,0,0,56,58,0.5899
4 | 2,3_shopping,public,0.0,0.0,0.0,0.8197,0.8197,0.0,0,59,63,0,0,0.0
5 | 3,driving,,0.0,0.0,0.0,0.8197,0.8043,0.0,0,0,0,64,67,1.388
6 | 4,6_home,home,0.0,0.0,0.0,0.8043,0.8043,0.0,0,68,128,0,0,0.0
7 | 5,driving,,0.0,0.0,0.0,0.8043,0.75,0.0,0,0,0,129,143,4.8933
8 | 6,0_work,work,0.0,0.0,0.0,0.75,0.75,0.0,0,144,176,0,0,0.0
9 | 7,driving,,0.0,0.0,0.0,0.75,0.744,0.0,0,0,0,177,178,0.5325
10 | 8,4_private/ridesharing,public,0.0,0.0,0.0,0.744,0.744,0.0,0,179,183,0,0,0.0
11 | 9,driving,,0.0,0.0,0.0,0.744,0.7219,0.0,0,0,0,184,223,1.991
12 | 10,0_work,work,0.0,0.0,0.0,0.7219,0.7219,0.0,0,224,237,0,0,0.0
13 | 11,driving,,0.0,0.0,0.0,0.7219,0.7145,0.0,0,0,0,238,239,0.6652
14 | 12,4_private/ridesharing,public,0.0,0.0,0.0,0.7145,0.7145,0.0,0,240,242,0,0,0.0
15 | 13,driving,,0.0,0.0,0.0,0.7145,0.5454,0.0,0,0,0,243,255,15.2255
16 | 14,0_work,work,0.0,0.0,0.0,0.5454,0.5454,0.0,0,256,277,0,0,0.0
17 | 15,driving,,0.0,0.0,0.0,0.5454,0.5383,0.0,0,0,0,278,285,0.6357
18 | 16,6_home,home,0.0,0.0,0.0,0.5383,0.5383,0.0,0,286,366,0,0,0.0
19 | 17,driving,,0.0,0.0,0.0,0.5383,0.5058,0.0,0,0,0,367,412,2.9197
20 | 18,0_work,work,0.0,0.0,0.0,0.5058,0.5058,0.0,0,413,453,0,0,0.0
21 | 19,driving,,0.0,0.0,0.0,0.5058,0.4999,0.0,0,0,0,454,455,0.5325
22 | 20,4_private/ridesharing,public,0.0,0.0,0.0,0.4999,0.4999,0.0,0,456,458,0,0,0.0
23 | 21,driving,,0.0,0.0,0.0,0.4999,0.4829,0.0,0,0,0,459,464,1.5342
24 | 22,3_shopping,public,22.0,24.4444,22.0,0.4829,1.0,46.5403,72,465,536,0,0,0.0
25 | 23,driving,,0.0,0.0,0.0,1.0,0.9915,0.0,0,0,0,537,543,0.7611
26 | 24,6_home,home,0.0,0.0,0.0,0.9915,0.9915,0.0,0,544,583,0,0,0.0
27 | 25,driving,,0.0,0.0,0.0,0.9915,0.9836,0.0,0,0,0,584,606,0.714
28 | 26,0_work,work,0.0,0.0,0.0,0.9836,0.9836,0.0,0,607,631,0,0,0.0
29 | 27,driving,,0.0,0.0,0.0,0.9836,0.9637,0.0,0,0,0,632,636,1.7886
30 | 28,1_business,public,3.7,4.1111,3.7,0.9637,0.9637,0.0,0,637,640,0,0,0.0
31 | 29,driving,,0.0,0.0,0.0,0.9637,0.9483,0.0,0,0,0,641,642,1.388
32 | 30,6_home,home,0.0,0.0,0.0,0.9483,0.9483,0.0,0,643,644,0,0,0.0
33 | 31,driving,,0.0,0.0,0.0,0.9483,0.935,0.0,0,0,0,645,652,1.196
34 | 32,4_private/ridesharing,public,0.0,0.0,0.0,0.935,0.935,0.0,0,653,654,0,0,0.0
35 | 33,driving,,0.0,0.0,0.0,0.935,0.914,0.0,0,0,0,655,672,0.0
36 |
--------------------------------------------------------------------------------
/tests/data/simbev_example_scenario/5334032/bev_medium_00001_90kWh_SR_Mitte_events.csv:
--------------------------------------------------------------------------------
1 | ,location,use_case,nominal_charging_capacity_kW,grid_charging_capacity_kW,battery_charging_capacity_kW,soc_start,soc_end,chargingdemand_kWh,park_time_timesteps,park_start_timesteps,park_end_timesteps,drive_start_timesteps,drive_end_timesteps,consumption_kWh
2 | 0,0_work,work,22.0,24.4444,22.0,0.8844,1.0,10.4045,37,0,66,0,0,0.0
3 | 1,driving,,0.0,0.0,0.0,1.0,0.92,0.0,0,0,0,67,72,7.1987
4 | 2,5_leisure,public,0.0,0.0,0.0,0.92,0.92,0.0,0,73,79,0,0,0.0
5 | 3,driving,,0.0,0.0,0.0,0.92,0.9046,0.0,0,0,0,80,92,1.388
6 | 4,6_home,public,0.0,0.0,0.0,0.9046,0.9046,0.0,0,93,102,0,0,0.0
7 | 5,driving,,0.0,0.0,0.0,0.9046,0.8972,0.0,0,0,0,103,140,0.6652
8 | 6,4_private/ridesharing,public,11.0,12.2222,11.0,0.8972,0.8972,0.0,0,141,147,0,0,0.0
9 | 7,driving,,0.0,0.0,0.0,0.8972,0.8553,0.0,0,0,0,148,152,3.7704
10 | 8,6_home,public,0.0,0.0,0.0,0.8553,0.8553,0.0,0,153,225,0,0,0.0
11 | 9,driving,,0.0,0.0,0.0,0.8553,0.8395,0.0,0,0,0,226,233,1.4185
12 | 10,5_leisure,public,22.0,24.4444,22.0,0.8395,0.8395,0.0,0,234,237,0,0,0.0
13 | 11,driving,,0.0,0.0,0.0,0.8395,0.8004,0.0,0,0,0,238,241,3.5196
14 | 12,6_home,public,0.0,0.0,0.0,0.8004,0.8004,0.0,0,242,246,0,0,0.0
15 | 13,driving,,0.0,0.0,0.0,0.8004,0.769,0.0,0,0,0,247,248,2.8283
16 | 14,5_leisure,public,0.0,0.0,0.0,0.769,0.769,0.0,0,249,253,0,0,0.0
17 | 15,driving,,0.0,0.0,0.0,0.769,0.7536,0.0,0,0,0,254,256,1.388
18 | 16,6_home,public,0.0,0.0,0.0,0.7536,0.7536,0.0,0,257,264,0,0,0.0
19 | 17,driving,,0.0,0.0,0.0,0.7536,0.6454,0.0,0,0,0,265,275,9.7364
20 | 18,5_leisure,public,0.0,0.0,0.0,0.6454,0.6454,0.0,0,276,281,0,0,0.0
21 | 19,driving,,0.0,0.0,0.0,0.6454,0.6413,0.0,0,0,0,282,320,0.3657
22 | 20,2_school,public,0.0,0.0,0.0,0.6413,0.6413,0.0,0,321,322,0,0,0.0
23 | 21,driving,,0.0,0.0,0.0,0.6413,0.4438,0.0,0,0,0,323,341,17.7828
24 | 22,4_private/ridesharing,public,22.0,24.4444,22.0,0.4438,0.6271,16.5,3,342,344,0,0,0.0
25 | 23,driving,,0.0,0.0,0.0,0.6271,0.5959,0.0,0,0,0,345,348,2.8037
26 | 24,0_work,work,22.0,24.4444,22.0,0.5959,1.0,36.3654,27,349,375,0,0,0.0
27 | 25,driving,,0.0,0.0,0.0,1.0,0.9929,0.0,0,0,0,376,414,0.6422
28 | 26,1_business,public,0.0,0.0,0.0,0.9929,0.9929,0.0,0,415,422,0,0,0.0
29 | 27,driving,,0.0,0.0,0.0,0.9929,0.9839,0.0,0,0,0,423,424,0.8078
30 | 28,3_shopping,public,0.0,0.0,0.0,0.9839,0.9839,0.0,0,425,427,0,0,0.0
31 | 29,driving,,0.0,0.0,0.0,0.9839,0.9765,0.0,0,0,0,428,430,0.6652
32 | 30,4_private/ridesharing,public,0.0,0.0,0.0,0.9765,0.9765,0.0,0,431,436,0,0,0.0
33 | 31,driving,,0.0,0.0,0.0,0.9765,0.9513,0.0,0,0,0,437,441,2.2657
34 | 32,6_home,public,0.0,0.0,0.0,0.9513,0.9513,0.0,0,442,498,0,0,0.0
35 | 33,driving,,0.0,0.0,0.0,0.9513,0.8995,0.0,0,0,0,499,509,4.6611
36 | 34,0_work,work,22.0,24.4444,22.0,0.8995,1.0,9.042,22,510,531,0,0,0.0
37 | 35,driving,,0.0,0.0,0.0,1.0,0.9661,0.0,0,0,0,532,535,3.0537
38 | 36,4_private/ridesharing,public,0.0,0.0,0.0,0.9661,0.9661,0.0,0,536,549,0,0,0.0
39 | 37,driving,,0.0,0.0,0.0,0.9661,0.9548,0.0,0,0,0,550,557,1.0118
40 | 38,6_home,public,0.0,0.0,0.0,0.9548,0.9548,0.0,0,558,624,0,0,0.0
41 | 39,driving,,0.0,0.0,0.0,0.9548,0.9108,0.0,0,0,0,625,627,3.9646
42 | 40,0_work,work,22.0,24.4444,22.0,0.9108,1.0,8.0301,19,628,646,0,0,0.0
43 | 41,driving,,0.0,0.0,0.0,1.0,0.9762,0.0,0,0,0,647,648,2.1403
44 | 42,6_home,public,0.0,0.0,0.0,0.9762,0.9762,0.0,0,649,672,0,0,0.0
45 |
--------------------------------------------------------------------------------
/tests/data/simbev_example_scenario/5334032/bev_medium_00002_90kWh_SR_Mitte_events.csv:
--------------------------------------------------------------------------------
1 | ,location,use_case,nominal_charging_capacity_kW,grid_charging_capacity_kW,battery_charging_capacity_kW,soc_start,soc_end,chargingdemand_kWh,park_time_timesteps,park_start_timesteps,park_end_timesteps,drive_start_timesteps,drive_end_timesteps,consumption_kWh
2 | 0,6_home,home,0.0,0.0,0.0,0.3735,0.3735,0.0,0,0,52,0,0,0.0
3 | 1,driving,,0.0,0.0,0.0,0.3735,0.2,0.0,0,0,0,53,59,15.6172
4 | 2,7_charging_hub,hpc,50.0,55.5556,50.0,0.2,0.3389,12.5,1,60,61,0,0,0.0
5 | 3,driving,,0.0,0.0,0.0,0.3389,0.2,0.0,0,0,0,62,67,12.5
6 | 4,7_charging_hub,hpc,50.0,55.5556,50.0,0.2,0.3389,12.5,1,68,69,0,0,0.0
7 | 5,driving,,0.0,0.0,0.0,0.3389,0.2314,0.0,0,0,0,70,75,9.6743
8 | 6,5_leisure,public,0.0,0.0,0.0,0.2314,0.2314,0.0,0,76,86,0,0,0.0
9 | 7,driving,,0.0,0.0,0.0,0.2314,0.2273,0.0,0,0,0,87,131,0.3719
10 | 8,3_shopping,public,0.0,0.0,0.0,0.2273,0.2273,0.0,0,132,133,0,0,0.0
11 | 9,driving,,0.0,0.0,0.0,0.2273,0.2,0.0,0,0,0,134,141,2.4537
12 | 10,7_charging_hub,hpc,50.0,55.5556,50.0,0.2,0.3389,12.5,1,142,143,0,0,0.0
13 | 11,driving,,0.0,0.0,0.0,0.3389,0.3253,0.0,0,0,0,144,146,1.2205
14 | 12,5_leisure,public,0.0,0.0,0.0,0.3253,0.3253,0.0,0,147,210,0,0,0.0
15 | 13,driving,,0.0,0.0,0.0,0.3253,0.298,0.0,0,0,0,211,220,2.4554
16 | 14,0_work,public,0.0,0.0,0.0,0.298,0.298,0.0,0,221,230,0,0,0.0
17 | 15,driving,,0.0,0.0,0.0,0.298,0.2,0.0,0,0,0,231,236,8.8241
18 | 16,7_charging_hub,hpc,50.0,55.5556,50.0,0.2,0.3389,12.5,1,237,238,0,0,0.0
19 | 17,driving,,0.0,0.0,0.0,0.3389,0.3322,0.0,0,0,0,239,240,0.5989
20 | 18,4_private/ridesharing,public,0.0,0.0,0.0,0.3322,0.3322,0.0,0,241,267,0,0,0.0
21 | 19,driving,,0.0,0.0,0.0,0.3322,0.3243,0.0,0,0,0,268,270,0.7136
22 | 20,5_leisure,public,3.7,4.1111,3.7,0.3243,0.3654,3.7,4,271,274,0,0,0.0
23 | 21,driving,,0.0,0.0,0.0,0.3654,0.3584,0.0,0,0,0,275,277,0.6357
24 | 22,6_home,home,0.0,0.0,0.0,0.3584,0.3584,0.0,0,278,291,0,0,0.0
25 | 23,driving,,0.0,0.0,0.0,0.3584,0.3491,0.0,0,0,0,292,318,0.83
26 | 24,2_school,public,0.0,0.0,0.0,0.3491,0.3491,0.0,0,319,330,0,0,0.0
27 | 25,driving,,0.0,0.0,0.0,0.3491,0.278,0.0,0,0,0,331,338,6.4036
28 | 26,6_home,home,0.0,0.0,0.0,0.278,0.278,0.0,0,339,375,0,0,0.0
29 | 27,driving,,0.0,0.0,0.0,0.278,0.2553,0.0,0,0,0,376,416,2.0427
30 | 28,3_shopping,public,22.0,24.4444,22.0,0.2553,0.4386,16.5,3,417,419,0,0,0.0
31 | 29,driving,,0.0,0.0,0.0,0.4386,0.4242,0.0,0,0,0,420,421,1.2945
32 | 30,0_work,public,0.0,0.0,0.0,0.4242,0.4242,0.0,0,422,463,0,0,0.0
33 | 31,driving,,0.0,0.0,0.0,0.4242,0.3768,0.0,0,0,0,464,483,4.272
34 | 32,6_home,home,0.0,0.0,0.0,0.3768,0.3768,0.0,0,484,541,0,0,0.0
35 | 33,driving,,0.0,0.0,0.0,0.3768,0.3492,0.0,0,0,0,542,547,2.4786
36 | 34,3_shopping,public,22.0,24.4444,22.0,0.3492,0.5937,22.0,4,548,551,0,0,0.0
37 | 35,driving,,0.0,0.0,0.0,0.5937,0.5462,0.0,0,0,0,552,556,4.272
38 | 36,6_home,home,0.0,0.0,0.0,0.5462,0.5462,0.0,0,557,560,0,0,0.0
39 | 37,driving,,0.0,0.0,0.0,0.5462,0.5226,0.0,0,0,0,561,567,2.1234
40 | 38,5_leisure,public,11.0,12.2222,11.0,0.5226,1.0,42.9649,42,568,609,0,0,0.0
41 | 39,driving,,0.0,0.0,0.0,1.0,0.9943,0.0,0,0,0,610,611,0.5103
42 | 40,6_home,home,0.0,0.0,0.0,0.9943,0.9943,0.0,0,612,672,0,0,0.0
43 |
--------------------------------------------------------------------------------
/tests/data/simbev_example_scenario/5334032/bev_mini_00000_60kWh_SR_Mitte_events.csv:
--------------------------------------------------------------------------------
1 | ,location,use_case,nominal_charging_capacity_kW,grid_charging_capacity_kW,battery_charging_capacity_kW,soc_start,soc_end,chargingdemand_kWh,park_time_timesteps,park_start_timesteps,park_end_timesteps,drive_start_timesteps,drive_end_timesteps,consumption_kWh
2 | 0,0_work,work,0.0,0.0,0.0,0.3798,0.3798,0.0,0,0,29,0,0,0.0
3 | 1,driving,,0.0,0.0,0.0,0.3798,0.3713,0.0,0,0,0,30,36,0.5086
4 | 2,6_home,public,0.0,0.0,0.0,0.3713,0.3713,0.0,0,37,40,0,0,0.0
5 | 3,driving,,0.0,0.0,0.0,0.3713,0.3553,0.0,0,0,0,41,44,0.9569
6 | 4,4_private/ridesharing,public,0.0,0.0,0.0,0.3553,0.3553,0.0,0,45,48,0,0,0.0
7 | 5,driving,,0.0,0.0,0.0,0.3553,0.3385,0.0,0,0,0,49,52,1.0102
8 | 6,6_home,public,0.0,0.0,0.0,0.3385,0.3385,0.0,0,53,60,0,0,0.0
9 | 7,driving,,0.0,0.0,0.0,0.3385,0.3314,0.0,0,0,0,61,62,0.4261
10 | 8,4_private/ridesharing,public,0.0,0.0,0.0,0.3314,0.3314,0.0,0,63,70,0,0,0.0
11 | 9,driving,,0.0,0.0,0.0,0.3314,0.3238,0.0,0,0,0,71,75,0.4582
12 | 10,5_leisure,public,11.0,12.2222,11.0,0.3238,1.0,40.5741,32,76,107,0,0,0.0
13 | 11,driving,,0.0,0.0,0.0,1.0,0.9894,0.0,0,0,0,108,134,0.6384
14 | 12,4_private/ridesharing,public,0.0,0.0,0.0,0.9894,0.9894,0.0,0,135,226,0,0,0.0
15 | 13,driving,,0.0,0.0,0.0,0.9894,0.8069,0.0,0,0,0,227,234,10.9487
16 | 14,5_leisure,public,0.0,0.0,0.0,0.8069,0.8069,0.0,0,235,244,0,0,0.0
17 | 15,driving,,0.0,0.0,0.0,0.8069,0.7399,0.0,0,0,0,245,250,4.02
18 | 16,6_home,public,0.0,0.0,0.0,0.7399,0.7399,0.0,0,251,314,0,0,0.0
19 | 17,driving,,0.0,0.0,0.0,0.7399,0.7195,0.0,0,0,0,315,317,1.2215
20 | 18,0_work,work,0.0,0.0,0.0,0.7195,0.7195,0.0,0,318,319,0,0,0.0
21 | 19,driving,,0.0,0.0,0.0,0.7195,0.6788,0.0,0,0,0,320,321,2.4433
22 | 20,4_private/ridesharing,public,0.0,0.0,0.0,0.6788,0.6788,0.0,0,322,326,0,0,0.0
23 | 21,driving,,0.0,0.0,0.0,0.6788,0.6496,0.0,0,0,0,327,340,1.7507
24 | 22,3_shopping,public,0.0,0.0,0.0,0.6496,0.6496,0.0,0,341,352,0,0,0.0
25 | 23,driving,,0.0,0.0,0.0,0.6496,0.6232,0.0,0,0,0,353,355,1.5862
26 | 24,5_leisure,public,11.0,12.2222,11.0,0.6232,0.8065,11.0,4,356,359,0,0,0.0
27 | 25,driving,,0.0,0.0,0.0,0.8065,0.7964,0.0,0,0,0,360,361,0.6089
28 | 26,6_home,public,0.0,0.0,0.0,0.7964,0.7964,0.0,0,362,451,0,0,0.0
29 | 27,driving,,0.0,0.0,0.0,0.7964,0.7389,0.0,0,0,0,452,509,3.4508
30 | 28,0_work,work,0.0,0.0,0.0,0.7389,0.7389,0.0,0,510,527,0,0,0.0
31 | 29,driving,,0.0,0.0,0.0,0.7389,0.727,0.0,0,0,0,528,529,0.7093
32 | 30,6_home,public,0.0,0.0,0.0,0.727,0.727,0.0,0,530,562,0,0,0.0
33 | 31,driving,,0.0,0.0,0.0,0.727,0.6969,0.0,0,0,0,563,569,1.8063
34 | 32,4_private/ridesharing,public,11.0,12.2222,11.0,0.6969,0.6969,0.0,0,570,587,0,0,0.0
35 | 33,driving,,0.0,0.0,0.0,0.6969,0.6859,0.0,0,0,0,588,599,0.6642
36 | 34,0_work,work,0.0,0.0,0.0,0.6859,0.6859,0.0,0,600,640,0,0,0.0
37 | 35,driving,,0.0,0.0,0.0,0.6859,0.6807,0.0,0,0,0,641,642,0.308
38 | 36,6_home,public,0.0,0.0,0.0,0.6807,0.6807,0.0,0,643,672,0,0,0.0
39 |
--------------------------------------------------------------------------------
/tests/data/simbev_example_scenario/5334032/bev_mini_00001_60kWh_SR_Mitte_events.csv:
--------------------------------------------------------------------------------
1 | ,location,use_case,nominal_charging_capacity_kW,grid_charging_capacity_kW,battery_charging_capacity_kW,soc_start,soc_end,chargingdemand_kWh,park_time_timesteps,park_start_timesteps,park_end_timesteps,drive_start_timesteps,drive_end_timesteps,consumption_kWh
2 | 0,6_home,home,0.0,0.0,0.0,0.603,0.603,0.0,0,0,32,0,0,0.0
3 | 1,driving,,0.0,0.0,0.0,0.603,0.5777,0.0,0,0,0,33,44,1.5182
4 | 2,3_shopping,public,11.0,12.2222,11.0,0.5777,0.8527,16.5,6,45,50,0,0,0.0
5 | 3,driving,,0.0,0.0,0.0,0.8527,0.8103,0.0,0,0,0,51,53,2.5495
6 | 4,4_private/ridesharing,public,0.0,0.0,0.0,0.8103,0.8103,0.0,0,54,61,0,0,0.0
7 | 5,driving,,0.0,0.0,0.0,0.8103,0.7784,0.0,0,0,0,62,65,1.9132
8 | 6,6_home,home,0.0,0.0,0.0,0.7784,0.7784,0.0,0,66,68,0,0,0.0
9 | 7,driving,,0.0,0.0,0.0,0.7784,0.7707,0.0,0,0,0,69,70,0.4582
10 | 8,5_leisure,public,11.0,12.2222,11.0,0.7707,0.7707,0.0,0,71,75,0,0,0.0
11 | 9,driving,,0.0,0.0,0.0,0.7707,0.7656,0.0,0,0,0,76,77,0.308
12 | 10,6_home,home,0.0,0.0,0.0,0.7656,0.7656,0.0,0,78,162,0,0,0.0
13 | 11,driving,,0.0,0.0,0.0,0.7656,0.726,0.0,0,0,0,163,165,2.3758
14 | 12,5_leisure,public,11.0,12.2222,11.0,0.726,1.0,16.4399,14,166,179,0,0,0.0
15 | 13,driving,,0.0,0.0,0.0,1.0,0.9642,0.0,0,0,0,180,220,2.1504
16 | 14,0_work,public,0.0,0.0,0.0,0.9642,0.9642,0.0,0,221,257,0,0,0.0
17 | 15,driving,,0.0,0.0,0.0,0.9642,0.959,0.0,0,0,0,258,259,0.308
18 | 16,6_home,home,0.0,0.0,0.0,0.959,0.959,0.0,0,260,273,0,0,0.0
19 | 17,driving,,0.0,0.0,0.0,0.959,0.9376,0.0,0,0,0,274,277,1.2857
20 | 18,3_shopping,public,0.0,0.0,0.0,0.9376,0.9376,0.0,0,278,372,0,0,0.0
21 | 19,driving,,0.0,0.0,0.0,0.9376,0.9191,0.0,0,0,0,373,376,1.1106
22 | 20,6_home,home,0.0,0.0,0.0,0.9191,0.9191,0.0,0,377,463,0,0,0.0
23 | 21,driving,,0.0,0.0,0.0,0.9191,0.887,0.0,0,0,0,464,469,1.925
24 | 22,3_shopping,public,11.0,12.2222,11.0,0.887,0.887,0.0,0,470,471,0,0,0.0
25 | 23,driving,,0.0,0.0,0.0,0.887,0.8744,0.0,0,0,0,472,507,0.7571
26 | 24,0_work,public,0.0,0.0,0.0,0.8744,0.8744,0.0,0,508,514,0,0,0.0
27 | 25,driving,,0.0,0.0,0.0,0.8744,0.8568,0.0,0,0,0,515,521,1.0532
28 | 26,3_shopping,public,11.0,12.2222,11.0,0.8568,0.8568,0.0,0,522,524,0,0,0.0
29 | 27,driving,,0.0,0.0,0.0,0.8568,0.7882,0.0,0,0,0,525,540,4.1203
30 | 28,6_home,home,0.0,0.0,0.0,0.7882,0.7882,0.0,0,541,597,0,0,0.0
31 | 29,driving,,0.0,0.0,0.0,0.7882,0.757,0.0,0,0,0,598,603,1.8717
32 | 30,0_work,public,0.0,0.0,0.0,0.757,0.757,0.0,0,604,613,0,0,0.0
33 | 31,driving,,0.0,0.0,0.0,0.757,0.7033,0.0,0,0,0,614,620,3.2174
34 | 32,6_home,home,0.0,0.0,0.0,0.7033,0.7033,0.0,0,621,672,0,0,0.0
35 |
--------------------------------------------------------------------------------
/tests/data/simbev_example_scenario/5334032/bev_mini_00002_60kWh_SR_Mitte_events.csv:
--------------------------------------------------------------------------------
1 | ,location,use_case,nominal_charging_capacity_kW,grid_charging_capacity_kW,battery_charging_capacity_kW,soc_start,soc_end,chargingdemand_kWh,park_time_timesteps,park_start_timesteps,park_end_timesteps,drive_start_timesteps,drive_end_timesteps,consumption_kWh
2 | 0,5_leisure,public,11.0,12.2222,11.0,0.9288,0.9288,0.0,0,0,33,0,0,0.0
3 | 1,driving,,0.0,0.0,0.0,0.9288,0.8845,0.0,0,0,0,34,37,2.6557
4 | 2,4_private/ridesharing,public,0.0,0.0,0.0,0.8845,0.8845,0.0,0,38,52,0,0,0.0
5 | 3,driving,,0.0,0.0,0.0,0.8845,0.8777,0.0,0,0,0,53,54,0.4083
6 | 4,6_home,home,0.0,0.0,0.0,0.8777,0.8777,0.0,0,55,73,0,0,0.0
7 | 5,driving,,0.0,0.0,0.0,0.8777,0.8437,0.0,0,0,0,74,78,2.0374
8 | 6,5_leisure,public,0.0,0.0,0.0,0.8437,0.8437,0.0,0,79,168,0,0,0.0
9 | 7,driving,,0.0,0.0,0.0,0.8437,0.8017,0.0,0,0,0,169,221,2.5219
10 | 8,0_work,work,11.0,12.2222,11.0,0.8017,1.0,11.8982,24,222,245,0,0,0.0
11 | 9,driving,,0.0,0.0,0.0,1.0,0.9805,0.0,0,0,0,246,252,1.1694
12 | 10,3_shopping,public,11.0,12.2222,11.0,0.9805,0.9805,0.0,0,253,254,0,0,0.0
13 | 11,driving,,0.0,0.0,0.0,0.9805,0.9704,0.0,0,0,0,255,256,0.6089
14 | 12,6_home,home,0.0,0.0,0.0,0.9704,0.9704,0.0,0,257,310,0,0,0.0
15 | 13,driving,,0.0,0.0,0.0,0.9704,0.8772,0.0,0,0,0,311,325,5.5872
16 | 14,0_work,work,11.0,12.2222,11.0,0.8772,1.0,7.3655,39,326,364,0,0,0.0
17 | 15,driving,,0.0,0.0,0.0,1.0,0.8761,0.0,0,0,0,365,387,7.4311
18 | 16,6_home,home,0.0,0.0,0.0,0.8761,0.8761,0.0,0,388,394,0,0,0.0
19 | 17,driving,,0.0,0.0,0.0,0.8761,0.8264,0.0,0,0,0,395,410,2.9863
20 | 18,0_work,work,11.0,12.2222,11.0,0.8264,1.0,10.4174,19,411,429,0,0,0.0
21 | 19,driving,,0.0,0.0,0.0,1.0,0.9924,0.0,0,0,0,430,431,0.4582
22 | 20,5_leisure,public,11.0,12.2222,11.0,0.9924,0.9924,0.0,0,432,525,0,0,0.0
23 | 21,driving,,0.0,0.0,0.0,0.9924,0.9855,0.0,0,0,0,526,527,0.4138
24 | 22,3_shopping,public,11.0,12.2222,11.0,0.9855,0.9855,0.0,0,528,532,0,0,0.0
25 | 23,driving,,0.0,0.0,0.0,0.9855,0.9722,0.0,0,0,0,533,538,0.7966
26 | 24,5_leisure,public,0.0,0.0,0.0,0.9722,0.9722,0.0,0,539,580,0,0,0.0
27 | 25,driving,,0.0,0.0,0.0,0.9722,0.9178,0.0,0,0,0,581,608,3.265
28 | 26,0_work,work,11.0,12.2222,11.0,0.9178,1.0,4.9336,26,609,634,0,0,0.0
29 | 27,driving,,0.0,0.0,0.0,1.0,0.9069,0.0,0,0,0,635,643,5.5867
30 | 28,3_shopping,public,0.0,0.0,0.0,0.9069,0.9069,0.0,0,644,648,0,0,0.0
31 | 29,driving,,0.0,0.0,0.0,0.9069,0.8899,0.0,0,0,0,649,650,1.0222
32 | 30,5_leisure,public,11.0,12.2222,11.0,0.8899,0.8899,0.0,0,651,672,0,0,0.0
33 |
--------------------------------------------------------------------------------
/tests/data/simbev_example_scenario/5334032/phev_luxury_00000_30kWh_SR_Mitte_events.csv:
--------------------------------------------------------------------------------
1 | ,location,use_case,nominal_charging_capacity_kW,grid_charging_capacity_kW,battery_charging_capacity_kW,soc_start,soc_end,chargingdemand_kWh,park_time_timesteps,park_start_timesteps,park_end_timesteps,drive_start_timesteps,drive_end_timesteps,consumption_kWh
2 | 0,6_home,public,3.7,4.1111,3.7,0.8934,1.0,1.3479,7,0,7,0,0,0.0
3 | 1,driving,,0.0,0.0,0.0,1.0,0.8633,0.0,0,0,0,8,43,4.1025
4 | 2,3_shopping,public,0.0,0.0,0.0,0.8633,0.8633,0.0,0,44,47,0,0,0.0
5 | 3,driving,,0.0,0.0,0.0,0.8633,0.8322,0.0,0,0,0,48,50,0.9319
6 | 4,6_home,public,3.7,4.1111,3.7,0.8322,1.0,5.0344,60,51,110,0,0,0.0
7 | 5,driving,,0.0,0.0,0.0,1.0,0.7887,0.0,0,0,0,111,143,6.3391
8 | 6,4_private/ridesharing,public,0.0,0.0,0.0,0.7887,0.7887,0.0,0,144,148,0,0,0.0
9 | 7,driving,,0.0,0.0,0.0,0.7887,0.7679,0.0,0,0,0,149,150,0.6249
10 | 8,6_home,public,3.7,4.1111,3.7,0.7679,1.0,6.9639,8,151,158,0,0,0.0
11 | 9,driving,,0.0,0.0,0.0,1.0,0.6392,0.0,0,0,0,159,220,10.8252
12 | 10,0_work,public,0.0,0.0,0.0,0.6392,0.6392,0.0,0,221,244,0,0,0.0
13 | 11,driving,,0.0,0.0,0.0,0.6392,0.621,0.0,0,0,0,245,246,0.5444
14 | 12,3_shopping,public,0.0,0.0,0.0,0.621,0.621,0.0,0,247,249,0,0,0.0
15 | 13,driving,,0.0,0.0,0.0,0.621,0.5804,0.0,0,0,0,250,252,1.2191
16 | 14,5_leisure,public,11.0,12.2222,11.0,0.5804,1.0,12.5887,6,253,258,0,0,0.0
17 | 15,driving,,0.0,0.0,0.0,1.0,0.9404,0.0,0,0,0,259,264,1.7895
18 | 16,4_private/ridesharing,public,0.0,0.0,0.0,0.9404,0.9404,0.0,0,265,269,0,0,0.0
19 | 17,driving,,0.0,0.0,0.0,0.9404,0.8076,0.0,0,0,0,270,273,3.9812
20 | 18,5_leisure,public,0.0,0.0,0.0,0.8076,0.8076,0.0,0,274,276,0,0,0.0
21 | 19,driving,,0.0,0.0,0.0,0.8076,0.7612,0.0,0,0,0,277,285,1.3926
22 | 20,6_home,public,3.7,4.1111,3.7,0.7612,1.0,7.1633,13,286,298,0,0,0.0
23 | 21,driving,,0.0,0.0,0.0,1.0,0.9827,0.0,0,0,0,299,320,0.5188
24 | 22,2_school,public,11.0,12.2222,11.0,0.9827,0.9827,0.0,0,321,341,0,0,0.0
25 | 23,driving,,0.0,0.0,0.0,0.9827,0.873,0.0,0,0,0,342,344,3.291
26 | 24,0_work,public,0.0,0.0,0.0,0.873,0.873,0.0,0,345,381,0,0,0.0
27 | 25,driving,,0.0,0.0,0.0,0.873,0.8341,0.0,0,0,0,382,420,1.1671
28 | 26,3_shopping,public,11.0,12.2222,11.0,0.8341,0.8341,0.0,0,421,424,0,0,0.0
29 | 27,driving,,0.0,0.0,0.0,0.8341,0.5881,0.0,0,0,0,425,443,7.3806
30 | 28,6_home,public,3.7,4.1111,3.7,0.5881,0.8347,7.4,8,444,451,0,0,0.0
31 | 29,driving,,0.0,0.0,0.0,0.8347,0.7999,0.0,0,0,0,452,458,1.0465
32 | 30,5_leisure,public,11.0,12.2222,11.0,0.7999,0.7999,0.0,0,459,466,0,0,0.0
33 | 31,driving,,0.0,0.0,0.0,0.7999,0.7684,0.0,0,0,0,467,510,0.9453
34 | 32,2_school,public,0.0,0.0,0.0,0.7684,0.7684,0.0,0,511,540,0,0,0.0
35 | 33,driving,,0.0,0.0,0.0,0.7684,0.6112,0.0,0,0,0,541,546,4.7142
36 | 34,4_private/ridesharing,public,0.0,0.0,0.0,0.6112,0.6112,0.0,0,547,552,0,0,0.0
37 | 35,driving,,0.0,0.0,0.0,0.6112,0.0,0.0,0,0,0,553,568,18.3365
38 | 36,6_home,public,3.7,4.1111,3.7,0.0,1.0,30.0,64,569,632,0,0,0.0
39 | 37,driving,,0.0,0.0,0.0,1.0,0.897,0.0,0,0,0,633,641,3.0894
40 | 38,4_private/ridesharing,public,0.0,0.0,0.0,0.897,0.897,0.0,0,642,649,0,0,0.0
41 | 39,driving,,0.0,0.0,0.0,0.897,0.8148,0.0,0,0,0,650,657,2.4673
42 | 40,6_home,public,3.7,4.1111,3.7,0.8148,0.8148,0.0,2,658,672,0,0,0.0
43 |
--------------------------------------------------------------------------------
/tests/data/simbev_example_scenario/5334032/phev_medium_00000_20kWh_SR_Mitte_events.csv:
--------------------------------------------------------------------------------
1 | ,location,use_case,nominal_charging_capacity_kW,grid_charging_capacity_kW,battery_charging_capacity_kW,soc_start,soc_end,chargingdemand_kWh,park_time_timesteps,park_start_timesteps,park_end_timesteps,drive_start_timesteps,drive_end_timesteps,consumption_kWh
2 | 0,5_leisure,public,11.0,12.2222,11.0,0.8557,0.8557,0.0,0,0,59,0,0,0.0
3 | 1,driving,,0.0,0.0,0.0,0.8557,0.7608,0.0,0,0,0,60,61,1.8978
4 | 2,4_private/ridesharing,public,0.0,0.0,0.0,0.7608,0.7608,0.0,0,62,66,0,0,0.0
5 | 3,driving,,0.0,0.0,0.0,0.7608,0.7219,0.0,0,0,0,67,68,0.7768
6 | 4,6_home,public,11.0,12.2222,11.0,0.7219,1.0,5.5612,15,69,83,0,0,0.0
7 | 5,driving,,0.0,0.0,0.0,1.0,0.5607,0.0,0,0,0,84,125,8.7857
8 | 6,0_work,work,11.0,12.2222,11.0,0.5607,1.0,8.7857,37,126,162,0,0,0.0
9 | 7,driving,,0.0,0.0,0.0,1.0,0.9187,0.0,0,0,0,163,166,1.6269
10 | 8,4_private/ridesharing,public,0.0,0.0,0.0,0.9187,0.9187,0.0,0,167,257,0,0,0.0
11 | 9,driving,,0.0,0.0,0.0,0.9187,0.8798,0.0,0,0,0,258,260,0.7768
12 | 10,6_home,public,11.0,12.2222,11.0,0.8798,1.0,2.4037,40,261,300,0,0,0.0
13 | 11,driving,,0.0,0.0,0.0,1.0,0.9032,0.0,0,0,0,301,316,1.9366
14 | 12,3_shopping,public,0.0,0.0,0.0,0.9032,0.9032,0.0,0,317,325,0,0,0.0
15 | 13,driving,,0.0,0.0,0.0,0.9032,0.8668,0.0,0,0,0,326,330,0.7283
16 | 14,5_leisure,public,11.0,12.2222,11.0,0.8668,0.8668,0.0,0,331,407,0,0,0.0
17 | 15,driving,,0.0,0.0,0.0,0.8668,0.8007,0.0,0,0,0,408,414,1.3212
18 | 16,0_work,work,11.0,12.2222,11.0,0.8007,1.0,3.9861,24,415,438,0,0,0.0
19 | 17,driving,,0.0,0.0,0.0,1.0,0.878,0.0,0,0,0,439,442,2.4404
20 | 18,6_home,public,11.0,12.2222,11.0,0.878,1.0,2.4404,72,443,514,0,0,0.0
21 | 19,driving,,0.0,0.0,0.0,1.0,0.981,0.0,0,0,0,515,518,0.3796
22 | 20,3_shopping,public,0.0,0.0,0.0,0.981,0.981,0.0,0,519,521,0,0,0.0
23 | 21,driving,,0.0,0.0,0.0,0.981,0.8116,0.0,0,0,0,522,530,3.3875
24 | 22,4_private/ridesharing,public,0.0,0.0,0.0,0.8116,0.8116,0.0,0,531,533,0,0,0.0
25 | 23,driving,,0.0,0.0,0.0,0.8116,0.7659,0.0,0,0,0,534,538,0.9154
26 | 24,1_business,public,11.0,12.2222,11.0,0.7659,1.0,4.6826,5,539,543,0,0,0.0
27 | 25,driving,,0.0,0.0,0.0,1.0,0.942,0.0,0,0,0,544,546,1.1607
28 | 26,6_home,public,11.0,12.2222,11.0,0.942,1.0,1.1607,89,547,635,0,0,0.0
29 | 27,driving,,0.0,0.0,0.0,1.0,0.9119,0.0,0,0,0,636,641,1.7624
30 | 28,4_private/ridesharing,public,0.0,0.0,0.0,0.9119,0.9119,0.0,0,642,643,0,0,0.0
31 | 29,driving,,0.0,0.0,0.0,0.9119,0.7747,0.0,0,0,0,644,648,2.7428
32 | 30,5_leisure,public,11.0,12.2222,11.0,0.7747,1.0,4.5051,7,649,655,0,0,0.0
33 | 31,driving,,0.0,0.0,0.0,1.0,0.8268,0.0,0,0,0,656,658,3.4642
34 | 32,6_home,public,11.0,12.2222,11.0,0.8268,0.8268,0.0,63,659,672,0,0,0.0
35 |
--------------------------------------------------------------------------------
/tests/data/simbev_example_scenario/5334032/phev_mini_00003_14kWh_SR_Mitte_events.csv:
--------------------------------------------------------------------------------
1 | ,location,use_case,nominal_charging_capacity_kW,grid_charging_capacity_kW,battery_charging_capacity_kW,soc_start,soc_end,chargingdemand_kWh,park_time_timesteps,park_start_timesteps,park_end_timesteps,drive_start_timesteps,drive_end_timesteps,consumption_kWh
2 | 0,6_home,home,0.0,0.0,0.0,0.9191,0.9191,0.0,0,0,17,0,0,0.0
3 | 1,driving,,0.0,0.0,0.0,0.9191,0.8889,0.0,0,0,0,18,30,0.4221
4 | 2,3_shopping,public,3.7,4.1111,3.7,0.8889,0.8889,0.0,0,31,34,0,0,0.0
5 | 3,driving,,0.0,0.0,0.0,0.8889,0.7805,0.0,0,0,0,35,38,1.5176
6 | 4,4_private/ridesharing,public,3.7,4.1111,3.7,0.7805,0.7805,0.0,0,39,41,0,0,0.0
7 | 5,driving,,0.0,0.0,0.0,0.7805,0.7362,0.0,0,0,0,42,43,0.6211
8 | 6,6_home,home,0.0,0.0,0.0,0.7362,0.7362,0.0,0,44,120,0,0,0.0
9 | 7,driving,,0.0,0.0,0.0,0.7362,0.6946,0.0,0,0,0,121,160,0.5824
10 | 8,5_leisure,public,3.7,4.1111,3.7,0.6946,0.6946,0.0,0,161,167,0,0,0.0
11 | 9,driving,,0.0,0.0,0.0,0.6946,0.3066,0.0,0,0,0,168,187,5.431
12 | 10,6_home,home,0.0,0.0,0.0,0.3066,0.3066,0.0,0,188,191,0,0,0.0
13 | 11,driving,,0.0,0.0,0.0,0.3066,0.2312,0.0,0,0,0,192,214,1.0565
14 | 12,0_work,public,0.0,0.0,0.0,0.2312,0.2312,0.0,0,215,245,0,0,0.0
15 | 13,driving,,0.0,0.0,0.0,0.2312,0.1795,0.0,0,0,0,246,255,0.7235
16 | 14,6_home,home,0.0,0.0,0.0,0.1795,0.1795,0.0,0,256,321,0,0,0.0
17 | 15,driving,,0.0,0.0,0.0,0.1795,0.0,0.0,0,0,0,322,328,2.5129
18 | 16,3_shopping,public,3.7,4.1111,3.7,0.0,0.1321,1.85,2,329,330,0,0,0.0
19 | 17,driving,,0.0,0.0,0.0,0.1321,0.0,0.0,0,0,0,331,333,1.85
20 | 18,6_home,home,0.0,0.0,0.0,0.0,0.0,0.0,0,334,352,0,0,0.0
21 | 19,driving,,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,353,357,0.0
22 | 20,5_leisure,public,0.0,0.0,0.0,0.0,0.0,0.0,0,358,380,0,0,0.0
23 | 21,driving,,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,381,413,0.0
24 | 22,0_work,public,0.0,0.0,0.0,0.0,0.0,0.0,0,414,453,0,0,0.0
25 | 23,driving,,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,454,461,0.0
26 | 24,6_home,home,0.0,0.0,0.0,0.0,0.0,0.0,0,462,536,0,0,0.0
27 | 25,driving,,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,537,545,0.0
28 | 26,4_private/ridesharing,public,3.7,4.1111,3.7,0.0,0.3304,4.625,5,546,550,0,0,0.0
29 | 27,driving,,0.0,0.0,0.0,0.3304,0.2641,0.0,0,0,0,551,554,0.9282
30 | 28,6_home,home,0.0,0.0,0.0,0.2641,0.2641,0.0,0,555,650,0,0,0.0
31 | 29,driving,,0.0,0.0,0.0,0.2641,0.2389,0.0,0,0,0,651,652,0.3523
32 | 30,5_leisure,public,0.0,0.0,0.0,0.2389,0.2389,0.0,0,653,659,0,0,0.0
33 | 31,driving,,0.0,0.0,0.0,0.2389,0.0,0.0,0,0,0,660,668,3.3445
34 | 32,6_home,home,0.0,0.0,0.0,0.0,0.0,0.0,0,669,672,0,0,0.0
35 |
--------------------------------------------------------------------------------
/tests/data/simbev_example_scenario/metadata_simbev_run.json:
--------------------------------------------------------------------------------
1 | {
2 | "simBEV_version": "0.1.3",
3 | "scenario": "default_multi",
4 | "timestamp_start": "2022-08-03_152333",
5 | "timestamp_end": "2022-08-03_152348",
6 | "config": {
7 | "region_mode": {
8 | "region_mode": "multi"
9 | },
10 | "basic": {
11 | "eta_cp": "0.9",
12 | "stepsize": "15",
13 | "start_date": "2011-01-01",
14 | "end_date": "2011-01-07",
15 | "soc_min": "0.2",
16 | "grid_timeseries": "false",
17 | "grid_timeseries_by_usecase": "false"
18 | },
19 | "rampup_ev": {
20 | "rampup": "regions_mobi_ws.csv"
21 | },
22 | "tech_data": {
23 | "tech_data": "tech_data.csv"
24 | },
25 | "charging_probabilities": {
26 | "slow": "charging_point_probability.csv",
27 | "fast": "fast_charging_probability.csv",
28 | "private_charging_home": "0.5",
29 | "private_charging_work": "0.7"
30 | },
31 | "sim_params": {
32 | "num_threads": "4",
33 | "seed": "3"
34 | }
35 | },
36 | "tech_data": {
37 | "bev_mini": {
38 | "max_charging_capacity_slow": 11.0,
39 | "max_charging_capacity_fast": 50,
40 | "battery_capacity": 60,
41 | "energy_consumption": 0.1397
42 | },
43 | "bev_medium": {
44 | "max_charging_capacity_slow": 22.0,
45 | "max_charging_capacity_fast": 50,
46 | "battery_capacity": 90,
47 | "energy_consumption": 0.1746
48 | },
49 | "bev_luxury": {
50 | "max_charging_capacity_slow": 50.0,
51 | "max_charging_capacity_fast": 150,
52 | "battery_capacity": 110,
53 | "energy_consumption": 0.2096
54 | },
55 | "phev_mini": {
56 | "max_charging_capacity_slow": 3.7,
57 | "max_charging_capacity_fast": 0,
58 | "battery_capacity": 14,
59 | "energy_consumption": 0.1425
60 | },
61 | "phev_medium": {
62 | "max_charging_capacity_slow": 11.0,
63 | "max_charging_capacity_fast": 0,
64 | "battery_capacity": 20,
65 | "energy_consumption": 0.1782
66 | },
67 | "phev_luxury": {
68 | "max_charging_capacity_slow": 11.0,
69 | "max_charging_capacity_fast": 0,
70 | "battery_capacity": 30,
71 | "energy_consumption": 0.2138
72 | }
73 | },
74 | "charge_prob_slow": {
75 | "work": {
76 | "0": 0.5887,
77 | "3.7": 0.0411,
78 | "11": 0.1645,
79 | "22": 0.1645,
80 | "50": 0.0411
81 | },
82 | "business": {
83 | "0": 0.64,
84 | "3.7": 0.033,
85 | "11": 0.135,
86 | "22": 0.15,
87 | "50": 0.042
88 | },
89 | "school": {
90 | "0": 0.5887,
91 | "3.7": 0.0411,
92 | "11": 0.1645,
93 | "22": 0.1645,
94 | "50": 0.0411
95 | },
96 | "shopping": {
97 | "0": 0.5588,
98 | "3.7": 0.0059,
99 | "11": 0.0618,
100 | "22": 0.253,
101 | "50": 0.1206
102 | },
103 | "private/ridesharing": {
104 | "0": 0.655,
105 | "3.7": 0.0155,
106 | "11": 0.081,
107 | "22": 0.176,
108 | "50": 0.0725
109 | },
110 | "leisure": {
111 | "0": 0.6538,
112 | "3.7": 0.0154,
113 | "11": 0.0808,
114 | "22": 0.177,
115 | "50": 0.0731
116 | },
117 | "home": {
118 | "0": 0.4894,
119 | "3.7": 0.0911,
120 | "11": 0.3402,
121 | "22": 0.0715,
122 | "50": 0.0079
123 | }
124 | },
125 | "charge_prob_fast": {
126 | "urban": {
127 | "50": 0,
128 | "150": 0.8,
129 | "350": 0.2
130 | },
131 | "ex-urban": {
132 | "50": 0,
133 | "150": 0.2,
134 | "350": 0.8
135 | }
136 | },
137 | "car_amount": {
138 | "bev_mini": 60,
139 | "bev_medium": 90,
140 | "bev_luxury": 30,
141 | "phev_mini": 20,
142 | "phev_medium": 40,
143 | "phev_luxury": 10
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/tests/data/tracbev_example_scenario/output_home_05334032.gpkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/tests/data/tracbev_example_scenario/output_home_05334032.gpkg
--------------------------------------------------------------------------------
/tests/data/tracbev_example_scenario/output_hpc_05334032.gpkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/tests/data/tracbev_example_scenario/output_hpc_05334032.gpkg
--------------------------------------------------------------------------------
/tests/data/tracbev_example_scenario/output_public_05334032.gpkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/tests/data/tracbev_example_scenario/output_public_05334032.gpkg
--------------------------------------------------------------------------------
/tests/data/tracbev_example_scenario/output_work_05334032.gpkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openego/eDisGo/63f242a1083700176e1896a637b550be74cd1196/tests/data/tracbev_example_scenario/output_work_05334032.gpkg
--------------------------------------------------------------------------------
/tests/flex_opt/test_charging_strategy.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | import pytest
3 |
4 | from edisgo.edisgo import EDisGo
5 | from edisgo.flex_opt.charging_strategies import charging_strategy
6 |
7 |
8 | class TestChargingStrategy:
9 | """
10 | Tests all charging strategies implemented in charging_strategies.py.
11 |
12 | """
13 |
14 | @classmethod
15 | def setup_class(cls):
16 | cls.ding0_path = pytest.ding0_test_network_2_path
17 | cls.simbev_path = pytest.simbev_example_scenario_path
18 | cls.tracbev_path = pytest.tracbev_example_scenario_path
19 | cls.standing_times_path = cls.simbev_path
20 | cls.charging_strategies = ["dumb", "reduced", "residual"]
21 |
22 | cls.edisgo_obj = EDisGo(ding0_grid=cls.ding0_path)
23 | timeindex = pd.date_range("1/1/2011", periods=24 * 7, freq="H")
24 | cls.edisgo_obj.set_timeindex(timeindex)
25 |
26 | cls.edisgo_obj.import_electromobility(
27 | data_source="directory",
28 | charging_processes_dir=cls.simbev_path,
29 | potential_charging_points_dir=cls.tracbev_path,
30 | )
31 |
32 | def test_charging_strategy(self, caplog):
33 | charging_demand_lst = []
34 |
35 | ts = self.edisgo_obj.timeseries
36 |
37 | for strategy in self.charging_strategies:
38 | charging_strategy(self.edisgo_obj, strategy=strategy)
39 |
40 | # Check if all charging points have a valid chargingdemand_kWh > 0
41 | df = ts.charging_points_active_power(self.edisgo_obj).loc[
42 | :, (ts.charging_points_active_power(self.edisgo_obj) <= 0).any(axis=0)
43 | ]
44 |
45 | assert df.shape == ts.charging_points_active_power(self.edisgo_obj).shape
46 |
47 | charging_demand_lst.append(
48 | ts.charging_points_active_power(self.edisgo_obj).sum()
49 | )
50 |
51 | # Check charging strategy for different timestamp_share_threshold value
52 | charging_strategy(
53 | self.edisgo_obj, strategy="dumb", timestamp_share_threshold=0.5
54 | )
55 |
56 | # Check if resampling warning is raised
57 | assert (
58 | "The frequency of the time series data of the edisgo object differs"
59 | in caplog.text
60 | )
61 |
62 | # Check if all charging points have a valid chargingdemand_kWh > 0
63 | df = ts.charging_points_active_power(self.edisgo_obj).loc[
64 | :, (ts.charging_points_active_power(self.edisgo_obj) <= 0).any(axis=0)
65 | ]
66 |
67 | assert df.shape == ts.charging_points_active_power(self.edisgo_obj).shape
68 |
69 | # Check charging strategy for different minimum_charging_capacity_factor
70 | charging_strategy(
71 | self.edisgo_obj, strategy="reduced", minimum_charging_capacity_factor=0.5
72 | )
73 |
74 | # Check if all charging points have a valid chargingdemand_kWh > 0
75 | df = ts.charging_points_active_power(self.edisgo_obj).loc[
76 | :, (ts.charging_points_active_power(self.edisgo_obj) <= 0).any(axis=0)
77 | ]
78 |
79 | assert df.shape == ts.charging_points_active_power(self.edisgo_obj).shape
80 |
81 | charging_demand_lst.append(
82 | ts.charging_points_active_power(self.edisgo_obj).sum()
83 | )
84 |
85 | # the chargingdemand_kWh per charging point and therefore in total should
86 | # always be the same
87 | assert all(
88 | (_.round(4) == charging_demand_lst[0].round(4)).all()
89 | for _ in charging_demand_lst
90 | )
91 |
92 | # ##################### check time index #####################
93 | assert ts._loads_active_power.index.freqstr == "H"
94 | # change time index to quarter-hourly
95 | timeindex = pd.date_range("1/1/2011", periods=24 * 7, freq="0.25H")
96 | self.edisgo_obj.set_timeindex(timeindex)
97 | charging_strategy(self.edisgo_obj, strategy="dumb")
98 | assert ts._loads_active_power.index.freqstr == "15T"
99 |
--------------------------------------------------------------------------------
/tests/flex_opt/test_heat_pump_operation.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | import pytest
3 |
4 | from edisgo import EDisGo
5 | from edisgo.flex_opt.heat_pump_operation import operating_strategy
6 |
7 |
8 | class TestHeatPumpOperation:
9 | @classmethod
10 | def setup_class(self):
11 | self.timeindex = pd.date_range("1/1/2011 12:00", periods=2, freq="H")
12 | self.cop = pd.DataFrame(
13 | data={
14 | "hp1": [5.0, 6.0],
15 | "hp2": [7.0, 8.0],
16 | },
17 | index=self.timeindex,
18 | )
19 | self.heat_demand = pd.DataFrame(
20 | data={
21 | "hp1": [1.0, 2.0],
22 | "hp2": [3.0, 4.0],
23 | },
24 | index=self.timeindex,
25 | )
26 | self.edisgo = EDisGo(
27 | ding0_grid=pytest.ding0_test_network_path, timeindex=self.timeindex
28 | )
29 | self.edisgo.heat_pump.cop_df = self.cop
30 | self.edisgo.heat_pump.heat_demand_df = self.heat_demand
31 |
32 | def test_operating_strategy(self):
33 | # test with default parameters
34 | operating_strategy(self.edisgo)
35 |
36 | hp_ts = pd.DataFrame(
37 | data={
38 | "hp1": [0.2, 1 / 3],
39 | "hp2": [3 / 7, 0.5],
40 | },
41 | index=self.timeindex,
42 | )
43 | pd.testing.assert_frame_equal(
44 | self.edisgo.timeseries.loads_active_power,
45 | hp_ts,
46 | )
47 | hp_ts = pd.DataFrame(
48 | data={
49 | "hp1": [0.0, 0.0],
50 | "hp2": [0.0, 0.0],
51 | },
52 | index=self.timeindex,
53 | )
54 | pd.testing.assert_frame_equal(
55 | self.edisgo.timeseries.loads_reactive_power,
56 | hp_ts,
57 | )
58 |
59 | # test with providing heat pump names
60 | timestep = self.timeindex[0]
61 | self.edisgo.heat_pump.heat_demand_df.at[timestep, "hp1"] = 0.0
62 | self.edisgo.heat_pump.heat_demand_df.at[timestep, "hp2"] = 0.0
63 |
64 | operating_strategy(self.edisgo, heat_pump_names=["hp1"])
65 |
66 | assert self.edisgo.timeseries.loads_active_power.at[timestep, "hp1"] == 0.0
67 | assert self.edisgo.timeseries.loads_active_power.at[timestep, "hp2"] == 3 / 7
68 |
69 | # test error raising
70 | msg = "Heat pump operating strategy dummy is not a valid option."
71 | with pytest.raises(ValueError, match=msg):
72 | operating_strategy(self.edisgo, strategy="dummy")
73 |
--------------------------------------------------------------------------------
/tests/flex_opt/test_reinforce_grid.py:
--------------------------------------------------------------------------------
1 | import copy
2 |
3 | import numpy as np
4 | import pytest
5 |
6 | from numpy.testing import assert_array_equal
7 | from pandas.testing import assert_frame_equal
8 |
9 | from edisgo import EDisGo
10 | from edisgo.flex_opt.costs import grid_expansion_costs
11 | from edisgo.flex_opt.reinforce_grid import reinforce_grid, run_separate_lv_grids
12 |
13 |
14 | class TestReinforceGrid:
15 | """
16 | Here, currently only reinforce_grid function is tested.
17 | Other functions in reinforce_grid module are currently tested in test_edisgo module.
18 | """
19 |
20 | @classmethod
21 | def setup_class(cls):
22 | cls.edisgo = EDisGo(ding0_grid=pytest.ding0_test_network_path)
23 |
24 | cls.edisgo.set_time_series_worst_case_analysis()
25 |
26 | def test_reinforce_grid(self):
27 | modes = [None, "mv", "mvlv", "lv"]
28 |
29 | results_dict = {
30 | mode: reinforce_grid(edisgo=copy.deepcopy(self.edisgo), mode=mode)
31 | for mode in modes
32 | }
33 |
34 | for mode, result in results_dict.items():
35 | if mode is None:
36 | target = ["mv/lv", "mv", "lv"]
37 | elif mode == "mv":
38 | target = ["mv"]
39 | elif mode == "mvlv":
40 | target = ["mv", "mv/lv"]
41 | elif mode == "lv":
42 | target = ["mv/lv", "lv"]
43 | else:
44 | raise ValueError("Non existing mode")
45 |
46 | assert_array_equal(
47 | np.sort(target),
48 | np.sort(result.grid_expansion_costs.voltage_level.unique()),
49 | )
50 |
51 | for comparison_mode, comparison_result in results_dict.items():
52 | if mode != comparison_mode:
53 | with pytest.raises(AssertionError):
54 | assert_frame_equal(
55 | result.equipment_changes,
56 | comparison_result.equipment_changes,
57 | )
58 | # test reduced analysis
59 | res_reduced = reinforce_grid(
60 | edisgo=copy.deepcopy(self.edisgo),
61 | reduced_analysis=True,
62 | num_steps_loading=2,
63 | )
64 | assert len(res_reduced.i_res) == 2
65 |
66 | def test_run_separate_lv_grids(self):
67 | edisgo = copy.deepcopy(self.edisgo)
68 |
69 | edisgo.timeseries.scale_timeseries(p_scaling_factor=5, q_scaling_factor=5)
70 |
71 | lv_grids = [copy.deepcopy(g) for g in edisgo.topology.mv_grid.lv_grids]
72 |
73 | run_separate_lv_grids(edisgo)
74 |
75 | edisgo.results.grid_expansion_costs = grid_expansion_costs(edisgo)
76 | lv_grids_new = list(edisgo.topology.mv_grid.lv_grids)
77 |
78 | # check that no new lv grid only consist of the station
79 | for g in lv_grids_new:
80 | if g.id != 0:
81 | assert len(g.buses_df) > 1
82 |
83 | assert len(lv_grids_new) == 26
84 | assert np.isclose(edisgo.results.grid_expansion_costs.total_costs.sum(), 440.06)
85 |
86 | # check if all generators are still present
87 | assert np.isclose(
88 | sum(g.generators_df.p_nom.sum() for g in lv_grids),
89 | sum(g.generators_df.p_nom.sum() for g in lv_grids_new),
90 | )
91 |
92 | # check if all loads are still present
93 | assert np.isclose(
94 | sum(g.loads_df.p_set.sum() for g in lv_grids),
95 | sum(g.loads_df.p_set.sum() for g in lv_grids_new),
96 | )
97 |
98 | # check if all storages are still present
99 | assert np.isclose(
100 | sum(g.storage_units_df.p_nom.sum() for g in lv_grids),
101 | sum(g.storage_units_df.p_nom.sum() for g in lv_grids_new),
102 | )
103 |
104 | # test if power flow works
105 | edisgo.set_time_series_worst_case_analysis()
106 | edisgo.analyze()
107 |
--------------------------------------------------------------------------------
/tests/io/test_ding0_import.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import shapely
3 |
4 | from edisgo.io import ding0_import
5 | from edisgo.network.grids import MVGrid
6 | from edisgo.network.topology import Topology
7 |
8 |
9 | class TestImportFromDing0:
10 | @classmethod
11 | def setup_class(self):
12 | self.topology = Topology()
13 |
14 | def test_import_ding0_grid(self):
15 | """Test successful import of ding0 network."""
16 |
17 | ding0_import.import_ding0_grid(pytest.ding0_test_network_path, self)
18 |
19 | # buses, generators, loads, lines, transformers dataframes
20 | # check number of imported components
21 | assert self.topology.buses_df.shape[0] == 142
22 | assert self.topology.generators_df.shape[0] == 28
23 | assert self.topology.loads_df.shape[0] == 50
24 | assert self.topology.lines_df.shape[0] == 131
25 | assert self.topology.transformers_df.shape[0] == 14
26 | assert self.topology.transformers_hvmv_df.shape[0] == 1
27 | assert self.topology.switches_df.shape[0] == 2
28 | assert self.topology.storage_units_df.shape[0] == 1
29 |
30 | # grid district
31 | assert self.topology.grid_district["population"] == 23358
32 | assert isinstance(self.topology.grid_district["geom"], shapely.geometry.Polygon)
33 |
34 | # grids
35 | assert isinstance(self.topology.mv_grid, MVGrid)
36 | lv_grid = self.topology.get_lv_grid(3)
37 | assert len(lv_grid.buses_df) == 9
38 |
39 | def test_path_error(self):
40 | """Test catching error when path to network does not exist."""
41 | msg = "Directory wrong_directory does not exist."
42 | with pytest.raises(AssertionError, match=msg):
43 | ding0_import.import_ding0_grid("wrong_directory", self.topology)
44 |
45 | def test_transformer_buses(self):
46 | ding0_import.import_ding0_grid(pytest.ding0_test_network_path, self)
47 | assert (
48 | self.topology.buses_df.loc[self.topology.transformers_df.bus1].v_nom.values
49 | < self.topology.buses_df.loc[
50 | self.topology.transformers_df.bus0
51 | ].v_nom.values
52 | ).all()
53 | self.topology.transformers_df.loc[
54 | "LVStation_7_transformer_1", "bus0"
55 | ] = "Bus_secondary_LVStation_7"
56 | self.topology.transformers_df.loc[
57 | "LVStation_7_transformer_1", "bus1"
58 | ] = "Bus_primary_LVStation_7"
59 | with pytest.raises(AssertionError):
60 | assert (
61 | self.topology.buses_df.reindex(
62 | index=self.topology.transformers_df.bus1
63 | ).v_nom.values
64 | < self.topology.buses_df.reindex(
65 | index=self.topology.transformers_df.bus0
66 | ).v_nom.values
67 | ).all()
68 |
--------------------------------------------------------------------------------
/tests/io/test_dsm_import.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from edisgo import EDisGo
4 | from edisgo.io import dsm_import
5 |
6 |
7 | class TestDSMImport:
8 | def test_oedb(self):
9 | # test without industrial load
10 | edisgo_object = EDisGo(
11 | ding0_grid=pytest.ding0_test_network_3_path, legacy_ding0_grids=False
12 | )
13 | dsm_profiles = dsm_import.oedb(
14 | edisgo_object, scenario="eGon2035", engine=pytest.engine
15 | )
16 | for dsm_profile in ["e_max", "e_min", "p_max", "p_min"]:
17 | assert dsm_profiles[dsm_profile].shape == (8760, 87)
18 | assert (dsm_profiles["p_min"] <= 0.0).all().all()
19 | assert (dsm_profiles["e_min"] <= 0.0).all().all()
20 | assert (dsm_profiles["p_max"] >= 0.0).all().all()
21 | assert (dsm_profiles["e_max"] >= 0.0).all().all()
22 |
23 | # test with one industrial load
24 | dsm_load = edisgo_object.topology.loads_df[
25 | (edisgo_object.topology.loads_df.type == "conventional_load")
26 | & (edisgo_object.topology.loads_df.sector == "cts")
27 | ].index[0]
28 | edisgo_object.topology.loads_df.at[dsm_load, "sector"] = "industrial"
29 | edisgo_object.topology.loads_df.at[dsm_load, "building_id"] = 1
30 |
31 | dsm_profiles = dsm_import.oedb(
32 | edisgo_object, scenario="eGon2035", engine=pytest.engine
33 | )
34 | for dsm_profile in ["e_max", "e_min", "p_max", "p_min"]:
35 | assert dsm_profiles[dsm_profile].shape == (8760, 87)
36 | assert dsm_load in dsm_profiles[dsm_profile].columns
37 | assert (dsm_profiles["p_min"] <= 0.0).all().all()
38 | assert (dsm_profiles["e_min"] <= 0.0).all().all()
39 | assert (dsm_profiles["p_max"] >= 0.0).all().all()
40 | assert (dsm_profiles["e_max"] >= 0.0).all().all()
41 |
42 | def test_get_profiles_per_industrial_load(self):
43 | dsm_profiles = dsm_import.get_profiles_per_industrial_load(
44 | load_ids=[15388, 241, 1], scenario="eGon2035", engine=pytest.engine
45 | )
46 | for dsm_profile in ["e_max", "e_min", "p_max", "p_min"]:
47 | assert dsm_profiles[dsm_profile].shape == (8760, 3)
48 | assert sorted(dsm_profiles[dsm_profile].columns) == [1, 241, 15388]
49 | assert (dsm_profiles["p_min"] <= 0.0).all().all()
50 | assert (dsm_profiles["e_min"] <= 0.0).all().all()
51 | assert (dsm_profiles["p_max"] >= 0.0).all().all()
52 | assert (dsm_profiles["e_max"] >= 0.0).all().all()
53 |
54 | dsm_profiles = dsm_import.get_profiles_per_industrial_load(
55 | load_ids=[], scenario="eGon2035", engine=pytest.engine
56 | )
57 | assert dsm_profiles["p_min"].empty
58 |
59 | def test_get_profile_cts(self):
60 | edisgo = EDisGo(
61 | ding0_grid=pytest.ding0_test_network_3_path, legacy_ding0_grids=False
62 | )
63 | dsm_profiles = dsm_import.get_profile_cts(
64 | edisgo_obj=edisgo, scenario="eGon2035", engine=pytest.engine
65 | )
66 | for dsm_profile in ["e_max", "e_min", "p_max", "p_min"]:
67 | assert dsm_profiles[dsm_profile].shape == (8760, 85)
68 | assert (dsm_profiles["p_min"] <= 0.0).all().all()
69 | assert (dsm_profiles["e_min"] <= 0.0).all().all()
70 | assert (dsm_profiles["p_max"] >= 0.0).all().all()
71 | assert (dsm_profiles["e_max"] >= 0.0).all().all()
72 |
--------------------------------------------------------------------------------
/tests/network/test_components.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | import pytest
3 |
4 | from edisgo import EDisGo
5 | from edisgo.network.components import Generator, Load, Storage, Switch
6 |
7 |
8 | class TestComponents:
9 | # ToDo add tests for PotentialChargingParks
10 |
11 | @classmethod
12 | def setup_class(self):
13 | self.edisgo_obj = EDisGo(ding0_grid=pytest.ding0_test_network_path)
14 | self.edisgo_obj.set_time_series_worst_case_analysis()
15 |
16 | def test_load_class(self):
17 | """Test Load class getter, setter, methods"""
18 |
19 | load = Load(id="Load_agricultural_LVGrid_1_1", edisgo_obj=self.edisgo_obj)
20 |
21 | # test getter
22 | assert load.id == "Load_agricultural_LVGrid_1_1"
23 | assert load.p_set == 0.0523
24 | assert load.annual_consumption == 238
25 | assert load.sector == "agricultural"
26 | assert load.bus == "Bus_BranchTee_LVGrid_1_2"
27 | assert str(load.grid) == "LVGrid_1"
28 | assert load.voltage_level == "lv"
29 | assert load.geom is None
30 | assert isinstance(load.active_power_timeseries, pd.Series)
31 | assert isinstance(load.reactive_power_timeseries, pd.Series)
32 |
33 | # test setter
34 | load.p_set = 0.06
35 | assert load.p_set == 0.06
36 | load.annual_consumption = 4
37 | assert load.annual_consumption == 4
38 | load.sector = "residential"
39 | assert load.sector == "residential"
40 | load.bus = "Bus_BranchTee_MVGrid_1_1"
41 | assert load.bus == "Bus_BranchTee_MVGrid_1_1"
42 | assert load.grid == self.edisgo_obj.topology.mv_grid
43 | assert load.voltage_level == "mv"
44 | msg = "Given bus ID does not exist."
45 | with pytest.raises(AttributeError, match=msg):
46 | load.bus = "None"
47 | # TODO: add test for active_power_timeseries and reactive_power_timeseries once
48 | # implemented
49 |
50 | def test_generator_class(self):
51 | """Test Generator class getter, setter, methods"""
52 |
53 | gen = Generator(id="GeneratorFluctuating_7", edisgo_obj=self.edisgo_obj)
54 | # GeneratorFluctuating_7,Bus_GeneratorFluctuating_7,PQ,3,wind,1122075,wind_wind_onshore
55 | # test getter
56 | assert gen.id == "GeneratorFluctuating_7"
57 | assert gen.bus == "Bus_GeneratorFluctuating_7"
58 | assert gen.grid == self.edisgo_obj.topology.mv_grid
59 | assert gen.voltage_level == "mv"
60 | assert pytest.approx(gen.geom.x, abs=1e-10) == 7.97127568152858
61 | assert pytest.approx(gen.geom.y, abs=1e-10) == 48.0666552118727
62 | assert gen.nominal_power == 3
63 | assert gen.type == "wind"
64 | assert gen.subtype == "wind_wind_onshore"
65 | assert gen.weather_cell_id == 1122075
66 | assert isinstance(gen.active_power_timeseries, pd.Series)
67 | assert isinstance(gen.reactive_power_timeseries, pd.Series)
68 |
69 | # test setter
70 | gen.nominal_power = 4
71 | assert gen.nominal_power == 4
72 | gen.type = "solar"
73 | assert gen.type == "solar"
74 | gen.subtype = "rooftop"
75 | assert gen.subtype == "rooftop"
76 | gen.weather_cell_id = 2
77 | assert gen.weather_cell_id == 2
78 | gen.bus = "Bus_BranchTee_LVGrid_1_5"
79 | assert gen.bus == "Bus_BranchTee_LVGrid_1_5"
80 | assert str(gen.grid) == "LVGrid_1"
81 | assert gen.voltage_level == "lv"
82 | msg = "Given bus ID does not exist."
83 | with pytest.raises(AttributeError, match=msg):
84 | gen.bus = "None"
85 |
86 | def test_storage_class(self):
87 | """Test Storage class getter, setter, methods"""
88 |
89 | gen = Storage(id="Storage_1", edisgo_obj=self.edisgo_obj)
90 | assert gen.id == "Storage_1"
91 | assert gen.bus == "Bus_MVStation_1"
92 | assert gen.grid == self.edisgo_obj.topology.mv_grid
93 | assert gen.voltage_level == "mv"
94 | assert pytest.approx(gen.geom.x, abs=1e-10) == 7.94859122759009
95 | assert pytest.approx(gen.geom.y, abs=1e-10) == 48.0844553685898
96 | assert gen.nominal_power == 0.4
97 | assert isinstance(gen.active_power_timeseries, pd.Series)
98 | assert isinstance(gen.reactive_power_timeseries, pd.Series)
99 |
100 | # test setter
101 | gen.nominal_power = 4
102 | assert gen.nominal_power == 4
103 | gen.bus = "Bus_BranchTee_LVGrid_1_5"
104 | assert gen.bus == "Bus_BranchTee_LVGrid_1_5"
105 | assert str(gen.grid) == "LVGrid_1"
106 | assert gen.voltage_level == "lv"
107 | msg = "Given bus ID does not exist."
108 | with pytest.raises(AttributeError, match=msg):
109 | gen.bus = "None"
110 |
111 | def test_switch_class(self):
112 | """Test Switch class"""
113 |
114 | switch = Switch(id="circuit_breaker_1", edisgo_obj=self.edisgo_obj)
115 |
116 | # test getter
117 | assert switch.id == "circuit_breaker_1"
118 | assert switch.bus_closed == "BusBar_MVGrid_1_LVGrid_4_MV"
119 | assert switch.bus_open == "virtual_BusBar_MVGrid_1_LVGrid_4_MV"
120 | assert switch.branch == "Line_10031"
121 | assert switch.type == "Switch Disconnector"
122 | assert switch.state == "open"
123 | assert switch.grid == self.edisgo_obj.topology.mv_grid
124 | assert switch.voltage_level == "mv"
125 |
126 | # test setter
127 | switch.type = "test"
128 | assert switch.type == "test"
129 |
130 | # test methods
131 | switch.close()
132 | switch._state = None
133 | assert switch.state == "closed"
134 | switch.open()
135 | switch._state = None
136 | assert switch.state == "open"
137 |
--------------------------------------------------------------------------------
/tests/network/test_dsm.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import os
3 | import shutil
4 |
5 | import pandas as pd
6 | import pytest
7 |
8 | from edisgo.network.dsm import DSM
9 |
10 |
11 | class TestDSM:
12 | @pytest.yield_fixture(autouse=True)
13 | def setup_dsm_test_data(self):
14 | timeindex = pd.date_range("1/1/2011 12:00", periods=2, freq="H")
15 | self.p_max = pd.DataFrame(
16 | data={
17 | "load_1": [5.0, 6.0],
18 | "load_2": [7.0, 8.0],
19 | },
20 | index=timeindex,
21 | )
22 | self.p_min = pd.DataFrame(
23 | data={
24 | "load_1": [1.0, 2.0],
25 | "load_2": [3.0, 4.0],
26 | },
27 | index=timeindex,
28 | )
29 | self.e_max = pd.DataFrame(
30 | data={
31 | "load_1": [9.5, 10.5],
32 | "load_2": [0.9, 0.8],
33 | },
34 | index=timeindex,
35 | )
36 | self.e_min = pd.DataFrame(
37 | data={
38 | "load_1": [9.0, 10.0],
39 | "load_2": [0.7, 0.6],
40 | },
41 | index=timeindex,
42 | )
43 | self.dsm = DSM()
44 | self.dsm.p_max = self.p_max
45 | self.dsm.p_min = self.p_min
46 | self.dsm.e_max = self.e_max
47 | self.dsm.e_min = self.e_min
48 |
49 | def test_reduce_memory(self):
50 | # check with default value
51 | assert (self.dsm.p_max.dtypes == "float64").all()
52 | assert (self.dsm.e_max.dtypes == "float64").all()
53 |
54 | self.dsm.reduce_memory()
55 |
56 | assert (self.dsm.p_max.dtypes == "float32").all()
57 | assert (self.dsm.e_max.dtypes == "float32").all()
58 |
59 | # check arguments
60 | self.dsm.reduce_memory(to_type="float16", attr_to_reduce=["p_max"])
61 |
62 | assert (self.dsm.p_max.dtypes == "float16").all()
63 | assert (self.dsm.e_max.dtypes == "float32").all()
64 |
65 | # check with empty dataframes
66 | self.dsm.e_max = pd.DataFrame()
67 | self.dsm.reduce_memory()
68 |
69 | def test_to_csv(self):
70 | # test with default values
71 | save_dir = os.path.join(os.getcwd(), "dsm_csv")
72 | self.dsm.to_csv(save_dir)
73 |
74 | files_in_dir = os.listdir(save_dir)
75 | assert len(files_in_dir) == 4
76 | assert "p_min.csv" in files_in_dir
77 | assert "p_max.csv" in files_in_dir
78 | assert "e_min.csv" in files_in_dir
79 | assert "e_max.csv" in files_in_dir
80 |
81 | shutil.rmtree(save_dir)
82 |
83 | # test with reduce memory True, to_type = float16
84 | self.dsm.to_csv(save_dir, reduce_memory=True, to_type="float16")
85 |
86 | assert (self.dsm.e_min.dtypes == "float16").all()
87 | files_in_dir = os.listdir(save_dir)
88 | assert len(files_in_dir) == 4
89 |
90 | shutil.rmtree(save_dir, ignore_errors=True)
91 |
92 | def test_from_csv(self):
93 | # write to csv
94 | save_dir = os.path.join(os.getcwd(), "dsm_csv")
95 | self.dsm.to_csv(save_dir)
96 |
97 | # reset DSM object
98 | self.dsm = DSM()
99 |
100 | self.dsm.from_csv(save_dir)
101 |
102 | pd.testing.assert_frame_equal(
103 | self.dsm.p_min,
104 | self.p_min,
105 | check_freq=False,
106 | )
107 | pd.testing.assert_frame_equal(
108 | self.dsm.e_min,
109 | self.e_min,
110 | check_freq=False,
111 | )
112 |
113 | shutil.rmtree(save_dir)
114 |
115 | def test_check_integrity(self, caplog):
116 | timeindex = pd.date_range("1/1/2011 12:00", periods=2, freq="H")
117 | # create duplicate entries and loads that do not appear in each DSM dataframe
118 | self.dsm.p_max = pd.concat(
119 | [
120 | self.dsm.p_max,
121 | pd.DataFrame(
122 | data={
123 | "load_2": [5.0, 6.0],
124 | "load_3": [7.0, 8.0],
125 | },
126 | index=timeindex,
127 | ),
128 | ],
129 | axis=1,
130 | )
131 | self.dsm.p_min = pd.concat(
132 | [
133 | self.dsm.p_min,
134 | pd.DataFrame(
135 | data={
136 | "load_2": [5.0, 6.0],
137 | "load_3": [7.0, 8.0],
138 | },
139 | index=timeindex,
140 | ),
141 | ],
142 | axis=1,
143 | )
144 |
145 | with caplog.at_level(logging.WARNING):
146 | self.dsm.check_integrity()
147 | assert len(caplog.messages) == 5
148 | assert "DSM timeseries contain the following duplicates:" in caplog.text
149 | assert "DSM timeseries e_min is missing the following entries:" in caplog.text
150 | assert "DSM timeseries e_max is missing the following entries:" in caplog.text
151 | assert (
152 | "DSM timeseries p_min contains values larger than zero, which is not "
153 | "allowed." in caplog.text
154 | )
155 | assert (
156 | "DSM timeseries e_min contains values larger than zero, which is not "
157 | "allowed." in caplog.text
158 | )
159 |
160 | caplog.clear()
161 | # check for empty DSM class
162 | self.dsm = DSM()
163 | with caplog.at_level(logging.WARNING):
164 | self.dsm.check_integrity()
165 | assert len(caplog.text) == 0
166 |
--------------------------------------------------------------------------------
/tests/network/test_results.py:
--------------------------------------------------------------------------------
1 | import os
2 | import shutil
3 |
4 | import pandas as pd
5 |
6 | from edisgo.network.results import Results
7 | from edisgo.tools.config import Config
8 |
9 |
10 | class TestResults:
11 | """
12 | Tests Results class.
13 |
14 | """
15 |
16 | @classmethod
17 | def setup_class(self):
18 | self.config = Config()
19 | self.results = Results(self)
20 |
21 | def test_to_csv(self):
22 | # create dummy results
23 | timeindex = pd.date_range(
24 | "2011-04-16 00:00:00", "2011-04-16 02:00:00", freq="1H"
25 | )
26 | self.results.pfa_v_mag_pu_seed = pd.DataFrame(
27 | data=1.1094890328530983,
28 | columns=["bus1", "bus2"],
29 | index=timeindex,
30 | dtype="float64",
31 | )
32 | self.results.v_res = self.results.pfa_v_mag_pu_seed.copy()
33 | self.results.grid_expansion_costs = pd.DataFrame(
34 | data={"total_costs": [2, 3], "quantity": [1, 1]},
35 | index=["line1", "transformer2"],
36 | )
37 |
38 | cur_dir = os.getcwd()
39 |
40 | # test with default values
41 | self.results.to_csv(cur_dir)
42 |
43 | files_in_powerflow_results = os.listdir(
44 | os.path.join(cur_dir, "powerflow_results")
45 | )
46 | assert len(files_in_powerflow_results) == 1
47 | assert files_in_powerflow_results[0] == "voltages_pu.csv"
48 | files_in_grid_expansion_results = os.listdir(
49 | os.path.join(cur_dir, "grid_expansion_results")
50 | )
51 | assert len(files_in_grid_expansion_results) == 1
52 | assert files_in_grid_expansion_results[0] == "grid_expansion_costs.csv"
53 |
54 | shutil.rmtree(os.path.join(cur_dir, "powerflow_results"))
55 |
56 | # test with save_seed=True
57 | self.results.to_csv(cur_dir, save_seed=True)
58 |
59 | files_in_powerflow_results = os.listdir(
60 | os.path.join(cur_dir, "powerflow_results")
61 | )
62 | assert len(files_in_powerflow_results) == 2
63 | assert "pfa_v_mag_pu_seed.csv" in files_in_powerflow_results
64 |
65 | shutil.rmtree(os.path.join(cur_dir, "powerflow_results"))
66 | shutil.rmtree(os.path.join(cur_dir, "grid_expansion_results"))
67 |
68 | # test with provided parameters and reduce memory True
69 | self.results.pfa_p = self.results.v_res
70 | self.results.to_csv(
71 | cur_dir,
72 | parameters={"powerflow_results": ["v_res"]},
73 | reduce_memory=True,
74 | )
75 |
76 | files_in_powerflow_results = os.listdir(
77 | os.path.join(cur_dir, "powerflow_results")
78 | )
79 | assert len(files_in_powerflow_results) == 1
80 | assert "voltages_pu.csv" in files_in_powerflow_results
81 | assert not os.path.isfile(
82 | os.path.join(cur_dir, "grid_expansion_results", "grid_expansion_costs.csv")
83 | )
84 | assert self.results.v_res.bus1.dtype == "float32"
85 |
86 | shutil.rmtree(os.path.join(cur_dir, "powerflow_results"))
87 |
88 | os.remove(os.path.join(cur_dir, "measures.csv"))
89 |
90 | def test_from_csv(self):
91 | # create dummy results and save to csv
92 | timeindex = pd.date_range(
93 | "2011-04-16 00:00:00", "2011-04-16 02:00:00", freq="1H"
94 | )
95 | pfa_v_mag_pu_seed = pd.DataFrame(
96 | data=1.1094890328530983,
97 | columns=["bus1", "bus2"],
98 | index=timeindex,
99 | dtype="float64",
100 | )
101 | self.results.pfa_v_mag_pu_seed = pfa_v_mag_pu_seed
102 | self.results.v_res = self.results.pfa_v_mag_pu_seed.copy()
103 | self.results.pfa_p = self.results.pfa_v_mag_pu_seed.copy()
104 | self.results.pfa_q = self.results.pfa_v_mag_pu_seed.copy()
105 | grid_expansion_costs = pd.DataFrame(
106 | data={"total_costs": [2, 3], "quantity": [1, 1]},
107 | index=["line1", "transformer2"],
108 | )
109 | self.results.grid_expansion_costs = grid_expansion_costs
110 | self.results.measures = "test"
111 |
112 | cur_dir = os.getcwd()
113 |
114 | self.results.to_csv(cur_dir, save_seed=True)
115 |
116 | # reset self.results
117 | self.results = Results(self)
118 |
119 | # test with default values
120 | self.results.from_csv(cur_dir)
121 |
122 | pd.testing.assert_frame_equal(
123 | self.results.pfa_v_mag_pu_seed, pfa_v_mag_pu_seed, check_freq=False
124 | )
125 | pd.testing.assert_frame_equal(
126 | self.results.v_res, pfa_v_mag_pu_seed, check_freq=False
127 | )
128 | pd.testing.assert_frame_equal(
129 | self.results.grid_expansion_costs, grid_expansion_costs
130 | )
131 | assert self.results.measures == ["original", "test"]
132 |
133 | # reset self.results
134 | self.results = Results(self)
135 |
136 | # test with given parameters
137 | self.results.from_csv(cur_dir, parameters={"powerflow_results": ["v_res"]})
138 |
139 | pd.testing.assert_frame_equal(
140 | self.results.v_res, pfa_v_mag_pu_seed, check_freq=False
141 | )
142 | assert self.results.pfa_v_mag_pu_seed.empty
143 | assert self.results.grid_expansion_costs.empty
144 |
145 | shutil.rmtree(os.path.join(cur_dir, "powerflow_results"))
146 | shutil.rmtree(os.path.join(cur_dir, "grid_expansion_results"))
147 |
148 | os.remove(os.path.join(cur_dir, "measures.csv"))
149 |
--------------------------------------------------------------------------------
/tests/test_examples.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import os
3 |
4 | import pytest
5 | import pytest_notebook
6 |
7 |
8 | class TestExamples:
9 | @classmethod
10 | def setup_class(self):
11 | self.examples_dir_path = os.path.join(
12 | os.path.dirname(os.path.dirname(__file__)), "examples"
13 | )
14 |
15 | @pytest.mark.slow
16 | def test_plot_example_ipynb(self):
17 | path = os.path.join(self.examples_dir_path, "plot_example.ipynb")
18 | notebook = pytest_notebook.notebook.load_notebook(path=path)
19 | result = pytest_notebook.execution.execute_notebook(
20 | notebook,
21 | with_coverage=False,
22 | timeout=600,
23 | )
24 | if result.exec_error is not None:
25 | print(result.exec_error)
26 | assert result.exec_error is None
27 |
28 | @pytest.mark.slow
29 | def test_electromobility_example_ipynb(self):
30 | path = os.path.join(self.examples_dir_path, "electromobility_example.ipynb")
31 | notebook = pytest_notebook.notebook.load_notebook(path=path)
32 | result = pytest_notebook.execution.execute_notebook(
33 | notebook,
34 | with_coverage=False,
35 | timeout=600,
36 | )
37 | if result.exec_error is not None:
38 | print(result.exec_error)
39 | assert result.exec_error is None
40 |
41 | @pytest.mark.slow
42 | def test_edisgo_simple_example_ipynb(self):
43 | path = os.path.join(self.examples_dir_path, "edisgo_simple_example.ipynb")
44 | notebook = pytest_notebook.notebook.load_notebook(path=path)
45 | result = pytest_notebook.execution.execute_notebook(
46 | notebook,
47 | with_coverage=False,
48 | timeout=600,
49 | )
50 | if result.exec_error is not None:
51 | print(result.exec_error)
52 | assert result.exec_error is None
53 |
54 | @classmethod
55 | def teardown_class(cls):
56 | logger = logging.getLogger("edisgo")
57 | logger.handlers.clear()
58 | logger.propagate = True
59 |
--------------------------------------------------------------------------------
/tests/tools/test_geopandas_helper.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from edisgo import EDisGo
4 | from edisgo.tools import geopandas_helper
5 |
6 |
7 | class TestGeopandasHelper:
8 | @classmethod
9 | def setup_class(self):
10 | self.edisgo = EDisGo(ding0_grid=pytest.ding0_test_network_path)
11 |
12 | def test_to_geopandas(self):
13 | # further tests of this function are conducted in test_topology.py
14 | # test MV grid
15 | data = geopandas_helper.to_geopandas(self.edisgo.topology.mv_grid, 4326)
16 | assert data.buses_gdf.shape[0] == self.edisgo.topology.mv_grid.buses_df.shape[0]
17 | assert (
18 | data.buses_gdf.shape[1]
19 | == self.edisgo.topology.mv_grid.buses_df.shape[1] + 1 - 2
20 | )
21 | assert "geometry" in data.buses_gdf.columns
22 |
23 | assert data.lines_gdf.shape[0] == self.edisgo.topology.mv_grid.lines_df.shape[0]
24 | assert (
25 | data.lines_gdf.shape[1]
26 | == self.edisgo.topology.mv_grid.lines_df.shape[1] + 2
27 | )
28 | assert "geometry" in data.lines_gdf.columns
29 |
30 | assert data.loads_gdf.shape[0] == self.edisgo.topology.mv_grid.loads_df.shape[0]
31 | assert (
32 | data.loads_gdf.shape[1]
33 | == self.edisgo.topology.mv_grid.loads_df.shape[1] + 2
34 | )
35 | assert "geometry" in data.loads_gdf.columns
36 |
37 | assert (
38 | data.generators_gdf.shape[0]
39 | == self.edisgo.topology.mv_grid.generators_df.shape[0]
40 | )
41 | assert (
42 | data.generators_gdf.shape[1]
43 | == self.edisgo.topology.mv_grid.generators_df.shape[1] + 2
44 | )
45 | assert "geometry" in data.generators_gdf.columns
46 |
47 | assert (
48 | data.storage_units_gdf.shape[0]
49 | == self.edisgo.topology.mv_grid.storage_units_df.shape[0]
50 | )
51 | assert (
52 | data.storage_units_gdf.shape[1]
53 | == self.edisgo.topology.mv_grid.storage_units_df.shape[1] + 2
54 | )
55 | assert "geometry" in data.storage_units_gdf.columns
56 |
57 | assert (
58 | data.transformers_gdf.shape[0]
59 | == self.edisgo.topology.mv_grid.transformers_df.shape[0]
60 | )
61 | assert (
62 | data.transformers_gdf.shape[1]
63 | == self.edisgo.topology.mv_grid.transformers_df.shape[1] + 2
64 | )
65 | assert "geometry" in data.transformers_gdf.columns
66 |
--------------------------------------------------------------------------------
/tests/tools/test_logger.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import os
3 |
4 | import pytest
5 |
6 | from edisgo.tools.logger import setup_logger
7 |
8 |
9 | def check_file_output(filename, output):
10 | with open(filename) as file:
11 | last_line = file.readlines()[-1].split(" ")[3:]
12 | last_line = " ".join(last_line)
13 | assert last_line == output
14 |
15 |
16 | def reset_loggers(filename):
17 | logger = logging.getLogger("edisgo")
18 | logger.handlers.clear()
19 | logger.propagate = True
20 | # try removing file - when run on github for Windows removing the file leads
21 | # to a PermissionError
22 | try:
23 | os.remove(filename)
24 | except PermissionError:
25 | pass
26 |
27 |
28 | class TestClass:
29 | def test_setup_logger(self):
30 | filename = os.path.join(
31 | os.path.expanduser("~"), ".edisgo", "log", "test_log.log"
32 | )
33 | if os.path.exists(filename):
34 | os.remove(filename)
35 |
36 | setup_logger(
37 | loggers=[
38 | {"name": "root", "file_level": "debug", "stream_level": "debug"},
39 | {"name": "edisgo", "file_level": "debug", "stream_level": "debug"},
40 | ],
41 | file_name="test_log.log",
42 | log_dir="default",
43 | )
44 |
45 | logger = logging.getLogger("edisgo")
46 | # Test that edisgo logger writes to file.
47 | logger.debug("root")
48 | check_file_output(filename, "edisgo - DEBUG: root\n")
49 | # Test that root logger writes to file.
50 | logging.debug("root")
51 | check_file_output(filename, "root - DEBUG: root\n")
52 |
53 | reset_loggers(filename)
54 |
55 | @pytest.mark.runonlinux
56 | def test_setup_logger_2(self):
57 | """
58 | This test is only run on linux, as the log file is written to the user
59 | home directory, which is not allowed when tests are run on github.
60 |
61 | """
62 |
63 | # delete any existing log files
64 | log_files = [_ for _ in os.listdir(os.getcwd()) if ".log" in _]
65 | for log_file in log_files:
66 | os.remove(log_file)
67 |
68 | setup_logger(
69 | loggers=[
70 | {"name": "edisgo", "file_level": "debug", "stream_level": "debug"},
71 | ],
72 | reset_loggers=True,
73 | debug_message=True,
74 | )
75 | logger = logging.getLogger("edisgo")
76 |
77 | filename = [_ for _ in os.listdir(os.getcwd()) if ".log" in _][0]
78 | # Test that edisgo logger writes to file.
79 | logger.debug("edisgo")
80 | check_file_output(filename, "edisgo - DEBUG: edisgo\n")
81 | # Test that root logger doesn't write to file.
82 | logging.debug("root")
83 | check_file_output(filename, "edisgo - DEBUG: edisgo\n")
84 |
85 | reset_loggers(filename)
86 |
--------------------------------------------------------------------------------
/tests/tools/test_plots.py:
--------------------------------------------------------------------------------
1 | import copy
2 |
3 | import pytest
4 |
5 | from edisgo import EDisGo
6 | from edisgo.tools.plots import chosen_graph, plot_dash_app, plot_plotly
7 |
8 |
9 | class TestPlots:
10 | @classmethod
11 | def setup_class(cls):
12 | cls.edisgo_root = EDisGo(ding0_grid=pytest.ding0_test_network_path)
13 | cls.edisgo_root.set_time_series_worst_case_analysis()
14 | cls.edisgo_analyzed = copy.deepcopy(cls.edisgo_root)
15 | cls.edisgo_reinforced = copy.deepcopy(cls.edisgo_root)
16 | cls.edisgo_analyzed.analyze()
17 | cls.edisgo_reinforced.reinforce()
18 | cls.edisgo_reinforced.results.equipment_changes.loc[
19 | "Line_10006", "change"
20 | ] = "added"
21 |
22 | @pytest.mark.parametrize(
23 | "line_color,"
24 | "node_color,"
25 | "line_result_selection,"
26 | "node_result_selection,"
27 | "plot_map,"
28 | "pseudo_coordinates",
29 | [
30 | ("loading", "voltage_deviation", "min", "min", True, True),
31 | ("relative_loading", "adjacencies", "max", "max", False, False),
32 | ("reinforce", "adjacencies", "max", "min", True, False),
33 | ],
34 | )
35 | @pytest.mark.parametrize(
36 | "selected_timesteps",
37 | [
38 | None,
39 | "1970-01-01 01:00:00",
40 | ["1970-01-01 01:00:00", "1970-01-01 03:00:00"],
41 | ],
42 | )
43 | @pytest.mark.parametrize(
44 | "node_selection", [False, ["Bus_MVStation_1", "Bus_BranchTee_MVGrid_1_5"]]
45 | )
46 | @pytest.mark.parametrize(
47 | "edisgo_obj_name", ["edisgo_root", "edisgo_analyzed", "edisgo_reinforced"]
48 | )
49 | @pytest.mark.parametrize("grid_name", ["None", "LVGrid"])
50 | def test_plot_plotly(
51 | self,
52 | edisgo_obj_name,
53 | grid_name,
54 | line_color,
55 | node_color,
56 | line_result_selection,
57 | node_result_selection,
58 | selected_timesteps,
59 | plot_map,
60 | pseudo_coordinates,
61 | node_selection,
62 | ):
63 | if edisgo_obj_name == "edisgo_root":
64 | edisgo_obj = self.edisgo_root
65 | elif edisgo_obj_name == "edisgo_analyzed":
66 | edisgo_obj = self.edisgo_analyzed
67 | elif edisgo_obj_name == "edisgo_reinforced":
68 | edisgo_obj = self.edisgo_reinforced
69 |
70 | if grid_name == "None":
71 | grid = None
72 | elif grid_name == "LVGrid":
73 | grid = list(edisgo_obj.topology.mv_grid.lv_grids)[1]
74 |
75 | if (grid_name == "LVGrid") and (node_selection is not False):
76 | with pytest.raises(ValueError):
77 | plot_plotly(
78 | edisgo_obj=edisgo_obj,
79 | grid=grid,
80 | line_color=line_color,
81 | node_color=node_color,
82 | line_result_selection=line_result_selection,
83 | node_result_selection=node_result_selection,
84 | selected_timesteps=selected_timesteps,
85 | plot_map=plot_map,
86 | pseudo_coordinates=pseudo_coordinates,
87 | node_selection=node_selection,
88 | )
89 | else:
90 | plot_plotly(
91 | edisgo_obj=edisgo_obj,
92 | grid=grid,
93 | line_color=line_color,
94 | node_color=node_color,
95 | line_result_selection=line_result_selection,
96 | node_result_selection=node_result_selection,
97 | selected_timesteps=selected_timesteps,
98 | plot_map=plot_map,
99 | pseudo_coordinates=pseudo_coordinates,
100 | node_selection=node_selection,
101 | )
102 |
103 | def test_chosen_graph(self):
104 | chosen_graph(edisgo_obj=self.edisgo_root, selected_grid="Grid")
105 | grid = str(self.edisgo_root.topology.mv_grid)
106 | chosen_graph(edisgo_obj=self.edisgo_root, selected_grid=grid)
107 | grid = list(map(str, self.edisgo_root.topology.mv_grid.lv_grids))[0]
108 | chosen_graph(edisgo_obj=self.edisgo_root, selected_grid=grid)
109 |
110 | def test_plot_dash_app(self):
111 | # TODO: at the moment this doesn't really test anything. Add meaningful tests.
112 | # test if any errors occur when only passing one edisgo object
113 | plot_dash_app(
114 | edisgo_objects=self.edisgo_root,
115 | )
116 |
117 | # test if any errors occur when passing multiple edisgo objects
118 | plot_dash_app( # noqa: F841
119 | edisgo_objects={
120 | "edisgo_1": self.edisgo_root,
121 | "edisgo_2": self.edisgo_reinforced,
122 | }
123 | )
124 |
--------------------------------------------------------------------------------
/tests/tools/test_pseudo_coordinates.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pytest
3 |
4 | from edisgo import EDisGo
5 | from edisgo.tools.pseudo_coordinates import make_pseudo_coordinates
6 |
7 |
8 | class TestPseudoCoordinates:
9 | @classmethod
10 | def setup_class(cls):
11 | cls.edisgo_root = EDisGo(ding0_grid=pytest.ding0_test_network_path)
12 |
13 | def test_make_pseudo_coordinates(self):
14 | # test coordinates before
15 | coordinates = self.edisgo_root.topology.buses_df.loc[
16 | "Bus_BranchTee_LVGrid_1_9", ["x", "y"]
17 | ]
18 | assert round(coordinates[0], 5) != round(7.943307, 5)
19 | assert round(coordinates[1], 5) != round(48.080396, 5)
20 |
21 | # make pseudo coordinates
22 | make_pseudo_coordinates(self.edisgo_root, mv_coordinates=True)
23 |
24 | # test if the right coordinates are set for one node
25 | coordinates = self.edisgo_root.topology.buses_df.loc[
26 | "Bus_BranchTee_LVGrid_1_9", ["x", "y"]
27 | ]
28 | assert round(coordinates[0], 5) == round(7.943307, 5)
29 | assert round(coordinates[1], 5) == round(48.080396, 5)
30 |
31 | assert not self.edisgo_root.topology.buses_df.x.isin([np.NaN]).any()
32 |
--------------------------------------------------------------------------------