flixopt 1.0.12__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of flixopt might be problematic. Click here for more details.
- flixopt-1.0.12/.github/workflows/python-app.yaml +147 -0
- flixopt-1.0.12/.gitignore +9 -0
- flixopt-1.0.12/LICENSE +21 -0
- flixopt-1.0.12/PKG-INFO +174 -0
- flixopt-1.0.12/README.md +134 -0
- flixopt-1.0.12/examples/00_Minmal/minimal_example.py +67 -0
- flixopt-1.0.12/examples/01_Simple/simple_example.py +120 -0
- flixopt-1.0.12/examples/02_Complex/complex_example.py +203 -0
- flixopt-1.0.12/examples/02_Complex/complex_example_results.py +48 -0
- flixopt-1.0.12/examples/03_Calculation_types/Zeitreihen2020.csv +35137 -0
- flixopt-1.0.12/examples/03_Calculation_types/example_calculation_types.py +249 -0
- flixopt-1.0.12/flixOpt/__init__.py +32 -0
- flixopt-1.0.12/flixOpt/aggregation.py +430 -0
- flixopt-1.0.12/flixOpt/calculation.py +629 -0
- flixopt-1.0.12/flixOpt/commons.py +48 -0
- flixopt-1.0.12/flixOpt/components.py +614 -0
- flixopt-1.0.12/flixOpt/config.py +258 -0
- flixopt-1.0.12/flixOpt/config.yaml +10 -0
- flixopt-1.0.12/flixOpt/core.py +182 -0
- flixopt-1.0.12/flixOpt/effects.py +410 -0
- flixopt-1.0.12/flixOpt/elements.py +489 -0
- flixopt-1.0.12/flixOpt/features.py +942 -0
- flixopt-1.0.12/flixOpt/flow_system.py +351 -0
- flixopt-1.0.12/flixOpt/interface.py +203 -0
- flixopt-1.0.12/flixOpt/linear_converters.py +325 -0
- flixopt-1.0.12/flixOpt/math_modeling.py +1145 -0
- flixopt-1.0.12/flixOpt/plotting.py +712 -0
- flixopt-1.0.12/flixOpt/results.py +563 -0
- flixopt-1.0.12/flixOpt/solvers.py +21 -0
- flixopt-1.0.12/flixOpt/structure.py +733 -0
- flixopt-1.0.12/flixOpt/utils.py +134 -0
- flixopt-1.0.12/flixopt.egg-info/PKG-INFO +174 -0
- flixopt-1.0.12/flixopt.egg-info/SOURCES.txt +47 -0
- flixopt-1.0.12/flixopt.egg-info/dependency_links.txt +1 -0
- flixopt-1.0.12/flixopt.egg-info/requires.txt +19 -0
- flixopt-1.0.12/flixopt.egg-info/top_level.txt +4 -0
- flixopt-1.0.12/pics/architecture_flixOpt.png +0 -0
- flixopt-1.0.12/pics/flixOpt_plotting.jpg +0 -0
- flixopt-1.0.12/pics/pics.pptx +0 -0
- flixopt-1.0.12/pyproject.toml +105 -0
- flixopt-1.0.12/setup.cfg +4 -0
- flixopt-1.0.12/tests/__init__.py +0 -0
- flixopt-1.0.12/tests/ressources/Zeitreihen2020.csv +35137 -0
- flixopt-1.0.12/tests/run_all_tests.py +10 -0
- flixopt-1.0.12/tests/test_examples.py +49 -0
- flixopt-1.0.12/tests/test_functional.py +918 -0
- flixopt-1.0.12/tests/test_integration.py +877 -0
- flixopt-1.0.12/tests/test_plots.py +135 -0
- flixopt-1.0.12/tests/todos.txt +5 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
name: Python Package CI/CD
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main] # Run on pushes to main (after PR is merged)
|
|
6
|
+
tags:
|
|
7
|
+
- 'v*' # Trigger on version tags
|
|
8
|
+
pull_request:
|
|
9
|
+
branches: [main, next/*] # Run when PRs are created or updated
|
|
10
|
+
types: [opened, synchronize, reopened]
|
|
11
|
+
release:
|
|
12
|
+
types: [created] # Trigger when a release is created
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
lint:
|
|
16
|
+
runs-on: ubuntu-22.04
|
|
17
|
+
steps:
|
|
18
|
+
- name: Check out code
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Set up Python
|
|
22
|
+
uses: actions/setup-python@v4
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.11" # Ruff tasks can run with a single Python version
|
|
25
|
+
|
|
26
|
+
- name: Install Ruff
|
|
27
|
+
run: |
|
|
28
|
+
python -m pip install --upgrade pip
|
|
29
|
+
pip install ruff
|
|
30
|
+
|
|
31
|
+
- name: Run Ruff Linting
|
|
32
|
+
run: ruff check .
|
|
33
|
+
|
|
34
|
+
test:
|
|
35
|
+
runs-on: ubuntu-22.04
|
|
36
|
+
needs: lint # Run tests only after linting passes
|
|
37
|
+
strategy:
|
|
38
|
+
fail-fast: false # Continue testing other Python versions if one fails
|
|
39
|
+
matrix:
|
|
40
|
+
python-version: ['3.10', '3.11', '3.12']
|
|
41
|
+
|
|
42
|
+
steps:
|
|
43
|
+
- name: Check out code
|
|
44
|
+
uses: actions/checkout@v4
|
|
45
|
+
|
|
46
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
47
|
+
uses: actions/setup-python@v4
|
|
48
|
+
with:
|
|
49
|
+
python-version: ${{ matrix.python-version }}
|
|
50
|
+
|
|
51
|
+
- name: Install dependencies
|
|
52
|
+
run: |
|
|
53
|
+
python -m pip install --upgrade pip
|
|
54
|
+
pip install .[dev]
|
|
55
|
+
|
|
56
|
+
- name: Run tests
|
|
57
|
+
run: pytest -v -p no:warnings
|
|
58
|
+
|
|
59
|
+
publish-testpypi:
|
|
60
|
+
name: Publish to TestPyPI
|
|
61
|
+
runs-on: ubuntu-22.04
|
|
62
|
+
needs: [test] # Only run after tests pass
|
|
63
|
+
if: github.event_name == 'release' && github.event.action == 'created' # Only on release creation
|
|
64
|
+
|
|
65
|
+
steps:
|
|
66
|
+
- name: Checkout repository
|
|
67
|
+
uses: actions/checkout@v4
|
|
68
|
+
|
|
69
|
+
- name: Set up Python
|
|
70
|
+
uses: actions/setup-python@v4
|
|
71
|
+
with:
|
|
72
|
+
python-version: "3.11"
|
|
73
|
+
|
|
74
|
+
- name: Install dependencies
|
|
75
|
+
run: |
|
|
76
|
+
python -m pip install --upgrade pip
|
|
77
|
+
pip install build setuptools wheel twine
|
|
78
|
+
|
|
79
|
+
- name: Build the distribution
|
|
80
|
+
run: |
|
|
81
|
+
python -m build
|
|
82
|
+
|
|
83
|
+
- name: Upload to TestPyPI
|
|
84
|
+
run: |
|
|
85
|
+
twine upload --repository testpypi dist/* --verbose
|
|
86
|
+
env:
|
|
87
|
+
TWINE_USERNAME: __token__
|
|
88
|
+
TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
|
|
89
|
+
|
|
90
|
+
- name: Test install from TestPyPI
|
|
91
|
+
run: |
|
|
92
|
+
# Create a temporary environment to test installation
|
|
93
|
+
python -m venv test_env
|
|
94
|
+
source test_env/bin/activate
|
|
95
|
+
# Get the package name from the built distribution
|
|
96
|
+
PACKAGE_NAME=$(ls dist/*.tar.gz | head -n 1 | sed 's/dist\///' | sed 's/-[0-9].*$//')
|
|
97
|
+
# Install from TestPyPI with retry (TestPyPI can be slow to index)
|
|
98
|
+
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ $PACKAGE_NAME || \
|
|
99
|
+
(sleep 30 && pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ $PACKAGE_NAME) || \
|
|
100
|
+
(sleep 60 && pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ $PACKAGE_NAME)
|
|
101
|
+
# Basic import test
|
|
102
|
+
python -c "import flixOpt; print('Installation successful!')"
|
|
103
|
+
|
|
104
|
+
publish-pypi:
|
|
105
|
+
name: Publish to PyPI
|
|
106
|
+
runs-on: ubuntu-22.04
|
|
107
|
+
needs: [publish-testpypi] # Only run after TestPyPI publish succeeds
|
|
108
|
+
if: github.event_name == 'release' && github.event.action == 'created' # Only on release creation
|
|
109
|
+
|
|
110
|
+
steps:
|
|
111
|
+
- name: Checkout repository
|
|
112
|
+
uses: actions/checkout@v4
|
|
113
|
+
|
|
114
|
+
- name: Set up Python
|
|
115
|
+
uses: actions/setup-python@v4
|
|
116
|
+
with:
|
|
117
|
+
python-version: "3.11"
|
|
118
|
+
|
|
119
|
+
- name: Install dependencies
|
|
120
|
+
run: |
|
|
121
|
+
python -m pip install --upgrade pip
|
|
122
|
+
pip install build setuptools wheel twine
|
|
123
|
+
|
|
124
|
+
- name: Build the distribution
|
|
125
|
+
run: |
|
|
126
|
+
python -m build
|
|
127
|
+
|
|
128
|
+
- name: Upload to PyPI
|
|
129
|
+
run: |
|
|
130
|
+
twine upload dist/* --verbose
|
|
131
|
+
env:
|
|
132
|
+
TWINE_USERNAME: __token__
|
|
133
|
+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
|
134
|
+
|
|
135
|
+
- name: Verify PyPI installation
|
|
136
|
+
run: |
|
|
137
|
+
# Create a temporary environment to test installation
|
|
138
|
+
python -m venv prod_test_env
|
|
139
|
+
source prod_test_env/bin/activate
|
|
140
|
+
# Get the package name from the built distribution
|
|
141
|
+
PACKAGE_NAME=$(ls dist/*.tar.gz | head -n 1 | sed 's/dist\///' | sed 's/-[0-9].*$//')
|
|
142
|
+
# Wait for PyPI to index the package
|
|
143
|
+
sleep 60
|
|
144
|
+
# Install from PyPI
|
|
145
|
+
pip install $PACKAGE_NAME
|
|
146
|
+
# Basic import test
|
|
147
|
+
python -c "import flixOpt; print('PyPI installation successful!')"
|
flixopt-1.0.12/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Chair of Building Energy Systems and Heat Supply - TU Dresden
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
flixopt-1.0.12/PKG-INFO
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: flixopt
|
|
3
|
+
Version: 1.0.12
|
|
4
|
+
Summary: Vector based energy and material flow optimization framework in Python.
|
|
5
|
+
Author-email: "Chair of Building Energy Systems and Heat Supply, TU Dresden" <peter.stange@tu-dresden.de>, Felix Bumann <felixbumann387@gmail.com>, Felix Panitz <baumbude@googlemail.com>, Peter Stange <peter.stange@tu-dresden.de>
|
|
6
|
+
Maintainer-email: Felix Bumann <felixbumann387@gmail.com>, Peter Stange <peter.stange@tu-dresden.de>
|
|
7
|
+
License: MIT License
|
|
8
|
+
Project-URL: homepage, https://tu-dresden.de/ing/maschinenwesen/iet/gewv/forschung/forschungsprojekte/flixopt
|
|
9
|
+
Project-URL: repository, https://github.com/flixOpt/flixopt
|
|
10
|
+
Keywords: optimization,energy systems,numerical analysis
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Intended Audience :: Science/Research
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering
|
|
19
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
20
|
+
Requires-Python: <3.13,>=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: numpy<2,>=1.21.5
|
|
24
|
+
Requires-Dist: PyYAML>=6.0
|
|
25
|
+
Requires-Dist: Pyomo>=6.4.2
|
|
26
|
+
Requires-Dist: rich>=13.0.1
|
|
27
|
+
Requires-Dist: highspy>=1.5.3
|
|
28
|
+
Requires-Dist: pandas<3,>=2
|
|
29
|
+
Requires-Dist: matplotlib>=3.5.2
|
|
30
|
+
Requires-Dist: plotly>=5.15
|
|
31
|
+
Requires-Dist: tomli>=2.0.1
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest; extra == "dev"
|
|
34
|
+
Requires-Dist: ruff; extra == "dev"
|
|
35
|
+
Requires-Dist: pyvis==0.3.1; extra == "dev"
|
|
36
|
+
Requires-Dist: tsam>=2.3.1; extra == "dev"
|
|
37
|
+
Provides-Extra: full
|
|
38
|
+
Requires-Dist: pyvis==0.3.1; extra == "full"
|
|
39
|
+
Requires-Dist: tsam>=2.3.1; extra == "full"
|
|
40
|
+
|
|
41
|
+
# flixOpt: Energy and Material Flow Optimization Framework
|
|
42
|
+
|
|
43
|
+
**flixOpt** is a Python-based optimization framework designed to tackle energy and material flow problems using mixed-integer linear programming (MILP). Combining flexibility and efficiency, it provides a powerful platform for both dispatch and investment optimization challenges.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 🚀 Introduction
|
|
48
|
+
|
|
49
|
+
flixOpt was developed by [TU Dresden](https://github.com/gewv-tu-dresden) as part of the SMARTBIOGRID project, funded by the German Federal Ministry for Economic Affairs and Energy (FKZ: 03KB159B). Building on the Matlab-based flixOptMat framework (developed in the FAKS project), flixOpt also incorporates concepts from [oemof/solph](https://github.com/oemof/oemof-solph).
|
|
50
|
+
|
|
51
|
+
Although flixOpt is in its early stages, it is fully functional and ready for experimentation. It is used for investment and operation decisions by energy providing companys as well as research institutions. Feedback and collaboration are highly encouraged to help shape its future.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 📦 Installation
|
|
56
|
+
|
|
57
|
+
Install flixOpt directly into your environment using pip. Thanks to [HiGHS](https://github.com/ERGO-Code/HiGHS?tab=readme-ov-file), flixOpt can be used without further setup.
|
|
58
|
+
`pip install git+https://github.com/flixOpt/flixopt.git`
|
|
59
|
+
|
|
60
|
+
We recommend installing flixOpt with all dependencies, which enables interactive network visualizations by [pyvis](https://github.com/WestHealth/pyvis) and time series aggregation by [tsam](https://github.com/FZJ-IEK3-VSA/tsam).
|
|
61
|
+
`pip install "flixOpt[full] @ git+https://github.com/flixOpt/flixopt.git"`
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 🌟 Key Features and Concepts
|
|
66
|
+
|
|
67
|
+
### 💡 High-level Interface...
|
|
68
|
+
- flixOpt aims to provide a user-friendly interface for defining and solving energy systems, without sacrificing fine-grained control where necessary.
|
|
69
|
+
- This is achieved through a high-level interface with many optional or default parameters.
|
|
70
|
+
- The most important concepts are:
|
|
71
|
+
- **FlowSystem**: Represents the System that is modeled.
|
|
72
|
+
- **Flow**: A Flow represents a stream of matter or energy. In an Energy-System, it could be electricity [kW]
|
|
73
|
+
- **Bus**: A Bus represents a balancing node in the Energy-System, typically connecting a demand to a supply.
|
|
74
|
+
- **Component**: A Component is a physical entity that consumes or produces matter or energy. It can also transform matter or energy into other kinds of matter or energy.
|
|
75
|
+
- **Effect**: Flows and Components can have Effects, related to their usage (or size). Common effects are *costs*, *CO2-emissions*, *primary-energy-demand* or *area-demand*. One Effect is used as the optimization target. The others can be constrained.
|
|
76
|
+
- To simplify the modeling process, high-level **Components** (CHP, Boiler, Heat Pump, Cooling Tower, Storage, etc.) are availlable.
|
|
77
|
+
|
|
78
|
+
### 🎛️ ...with low-level control
|
|
79
|
+
- **Segmented Linear Correlations**
|
|
80
|
+
- Accurate modeling for efficiencies, investment effects, and sizes.
|
|
81
|
+
- **On/Off Variables**
|
|
82
|
+
- Modeling On/Off-Variables and their constraints.
|
|
83
|
+
- On-Hours/Off-Hours
|
|
84
|
+
- Consecutive On-Hours/ Off-Hours
|
|
85
|
+
- Switch On/Off
|
|
86
|
+
|
|
87
|
+
### 💰 Investment Optimization
|
|
88
|
+
- flixOpt combines dispatch optimization with investment optimization in one model.
|
|
89
|
+
- Size and/or discrete investment decisions can be modeled
|
|
90
|
+
- Investment decisions can be combined with Modeling On/Off-Variables and their constraints
|
|
91
|
+
|
|
92
|
+
### Further Features
|
|
93
|
+
- **Multiple Effects**
|
|
94
|
+
- Couple effects (e.g., specific CO2 costs) and set constraints (e.g., max CO2 emissions).
|
|
95
|
+
- Easily switch between optimization targets (e.g., minimize CO2 or costs).
|
|
96
|
+
- This allows to solve questions like "How much does it cost to reduce CO2 emissions by 20%?"
|
|
97
|
+
|
|
98
|
+
- **Advanced Time Handling**
|
|
99
|
+
- Non-equidistant timesteps supported.
|
|
100
|
+
- Energy prices or effects in general can always be defined per hour (or per MWh...)
|
|
101
|
+
|
|
102
|
+
- A variety of predefined constraints for operational and investment optimization can be applied.
|
|
103
|
+
- Many of these are optional and only applied when necessary, keeping the amount o variables and equations low.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## 🖥️ Usage Example
|
|
108
|
+

|
|
109
|
+
|
|
110
|
+
**Plotting examples**:
|
|
111
|
+

|
|
112
|
+
|
|
113
|
+
## ⚙️ Calculation Modes
|
|
114
|
+
|
|
115
|
+
flixOpt offers three calculation modes, tailored to different performance and accuracy needs:
|
|
116
|
+
|
|
117
|
+
- **Full Mode**
|
|
118
|
+
- Provides exact solutions with high computational requirements.
|
|
119
|
+
- Recommended for detailed analyses and investment decision problems.
|
|
120
|
+
|
|
121
|
+
- **Segmented Mode**
|
|
122
|
+
- Solving a Model segmentwise, this mode can speed up the solving process for complex systems, while being fairly accurate.
|
|
123
|
+
- Utilizes variable time overlap to improve accuracy.
|
|
124
|
+
- Not suitable for large storage systems or investment decisions.
|
|
125
|
+
|
|
126
|
+
- **Aggregated Mode**
|
|
127
|
+
- Automatically generates typical periods using [TSAM](https://github.com/FZJ-IEK3-VSA/tsam).
|
|
128
|
+
- Balances speed and accuracy, making it ideal for large-scale simulations.
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
## 🏗️ Architecture
|
|
132
|
+
|
|
133
|
+
- **Minimal coupling to Pyomo**
|
|
134
|
+
- Included independent module is used to organize variables and equations, independently of a specific modeling language.
|
|
135
|
+
- While currently only working with [Pyomo](http://www.pyomo.org/), flixOpt is designed to work with different modeling languages with minor modifications ([cvxpy](https://www.cvxpy.org)).
|
|
136
|
+
|
|
137
|
+
- **File-based Post-Processing Unit**
|
|
138
|
+
- Results are saved to .json and .yaml files for easy access and analysis anytime.
|
|
139
|
+
- Internal plotting functions utilizing matplotlib, plotly and pandas simplify results visualization and reporting.
|
|
140
|
+
|
|
141
|
+

|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## 🛠️ Solver Integration
|
|
146
|
+
|
|
147
|
+
By default, flixOpt uses the open-source solver [HiGHS](https://highs.dev/) which is installed by default. However, it is compatible with additional solvers such as:
|
|
148
|
+
|
|
149
|
+
- [CBC](https://github.com/coin-or/Cbc)
|
|
150
|
+
- [GLPK](https://www.gnu.org/software/glpk/)
|
|
151
|
+
- [Gurobi](https://www.gurobi.com/)
|
|
152
|
+
- [CPLEX](https://www.ibm.com/analytics/cplex-optimizer)
|
|
153
|
+
|
|
154
|
+
Executables can be found for example [here for CBC](https://portal.ampl.com/dl/open/cbc/) and [here for GLPK](https://sourceforge.net/projects/winglpk/) (Windows: You have to put solver-executables to the PATH-variable)
|
|
155
|
+
|
|
156
|
+
For detailed licensing and installation instructions, refer to the respective solver documentation.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 📖 Citation
|
|
161
|
+
|
|
162
|
+
If you use flixOpt in your research or project, please cite the following:
|
|
163
|
+
|
|
164
|
+
- **Main Citation:** [DOI:10.18086/eurosun.2022.04.07](https://doi.org/10.18086/eurosun.2022.04.07)
|
|
165
|
+
- **Short Overview:** [DOI:10.13140/RG.2.2.14948.24969](https://doi.org/10.13140/RG.2.2.14948.24969)
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 🔧 Development and Testing
|
|
170
|
+
|
|
171
|
+
Run the tests using:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
python -m unittest discover -s tests
|
flixopt-1.0.12/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# flixOpt: Energy and Material Flow Optimization Framework
|
|
2
|
+
|
|
3
|
+
**flixOpt** is a Python-based optimization framework designed to tackle energy and material flow problems using mixed-integer linear programming (MILP). Combining flexibility and efficiency, it provides a powerful platform for both dispatch and investment optimization challenges.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🚀 Introduction
|
|
8
|
+
|
|
9
|
+
flixOpt was developed by [TU Dresden](https://github.com/gewv-tu-dresden) as part of the SMARTBIOGRID project, funded by the German Federal Ministry for Economic Affairs and Energy (FKZ: 03KB159B). Building on the Matlab-based flixOptMat framework (developed in the FAKS project), flixOpt also incorporates concepts from [oemof/solph](https://github.com/oemof/oemof-solph).
|
|
10
|
+
|
|
11
|
+
Although flixOpt is in its early stages, it is fully functional and ready for experimentation. It is used for investment and operation decisions by energy providing companys as well as research institutions. Feedback and collaboration are highly encouraged to help shape its future.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 📦 Installation
|
|
16
|
+
|
|
17
|
+
Install flixOpt directly into your environment using pip. Thanks to [HiGHS](https://github.com/ERGO-Code/HiGHS?tab=readme-ov-file), flixOpt can be used without further setup.
|
|
18
|
+
`pip install git+https://github.com/flixOpt/flixopt.git`
|
|
19
|
+
|
|
20
|
+
We recommend installing flixOpt with all dependencies, which enables interactive network visualizations by [pyvis](https://github.com/WestHealth/pyvis) and time series aggregation by [tsam](https://github.com/FZJ-IEK3-VSA/tsam).
|
|
21
|
+
`pip install "flixOpt[full] @ git+https://github.com/flixOpt/flixopt.git"`
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 🌟 Key Features and Concepts
|
|
26
|
+
|
|
27
|
+
### 💡 High-level Interface...
|
|
28
|
+
- flixOpt aims to provide a user-friendly interface for defining and solving energy systems, without sacrificing fine-grained control where necessary.
|
|
29
|
+
- This is achieved through a high-level interface with many optional or default parameters.
|
|
30
|
+
- The most important concepts are:
|
|
31
|
+
- **FlowSystem**: Represents the System that is modeled.
|
|
32
|
+
- **Flow**: A Flow represents a stream of matter or energy. In an Energy-System, it could be electricity [kW]
|
|
33
|
+
- **Bus**: A Bus represents a balancing node in the Energy-System, typically connecting a demand to a supply.
|
|
34
|
+
- **Component**: A Component is a physical entity that consumes or produces matter or energy. It can also transform matter or energy into other kinds of matter or energy.
|
|
35
|
+
- **Effect**: Flows and Components can have Effects, related to their usage (or size). Common effects are *costs*, *CO2-emissions*, *primary-energy-demand* or *area-demand*. One Effect is used as the optimization target. The others can be constrained.
|
|
36
|
+
- To simplify the modeling process, high-level **Components** (CHP, Boiler, Heat Pump, Cooling Tower, Storage, etc.) are availlable.
|
|
37
|
+
|
|
38
|
+
### 🎛️ ...with low-level control
|
|
39
|
+
- **Segmented Linear Correlations**
|
|
40
|
+
- Accurate modeling for efficiencies, investment effects, and sizes.
|
|
41
|
+
- **On/Off Variables**
|
|
42
|
+
- Modeling On/Off-Variables and their constraints.
|
|
43
|
+
- On-Hours/Off-Hours
|
|
44
|
+
- Consecutive On-Hours/ Off-Hours
|
|
45
|
+
- Switch On/Off
|
|
46
|
+
|
|
47
|
+
### 💰 Investment Optimization
|
|
48
|
+
- flixOpt combines dispatch optimization with investment optimization in one model.
|
|
49
|
+
- Size and/or discrete investment decisions can be modeled
|
|
50
|
+
- Investment decisions can be combined with Modeling On/Off-Variables and their constraints
|
|
51
|
+
|
|
52
|
+
### Further Features
|
|
53
|
+
- **Multiple Effects**
|
|
54
|
+
- Couple effects (e.g., specific CO2 costs) and set constraints (e.g., max CO2 emissions).
|
|
55
|
+
- Easily switch between optimization targets (e.g., minimize CO2 or costs).
|
|
56
|
+
- This allows to solve questions like "How much does it cost to reduce CO2 emissions by 20%?"
|
|
57
|
+
|
|
58
|
+
- **Advanced Time Handling**
|
|
59
|
+
- Non-equidistant timesteps supported.
|
|
60
|
+
- Energy prices or effects in general can always be defined per hour (or per MWh...)
|
|
61
|
+
|
|
62
|
+
- A variety of predefined constraints for operational and investment optimization can be applied.
|
|
63
|
+
- Many of these are optional and only applied when necessary, keeping the amount o variables and equations low.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 🖥️ Usage Example
|
|
68
|
+

|
|
69
|
+
|
|
70
|
+
**Plotting examples**:
|
|
71
|
+

|
|
72
|
+
|
|
73
|
+
## ⚙️ Calculation Modes
|
|
74
|
+
|
|
75
|
+
flixOpt offers three calculation modes, tailored to different performance and accuracy needs:
|
|
76
|
+
|
|
77
|
+
- **Full Mode**
|
|
78
|
+
- Provides exact solutions with high computational requirements.
|
|
79
|
+
- Recommended for detailed analyses and investment decision problems.
|
|
80
|
+
|
|
81
|
+
- **Segmented Mode**
|
|
82
|
+
- Solving a Model segmentwise, this mode can speed up the solving process for complex systems, while being fairly accurate.
|
|
83
|
+
- Utilizes variable time overlap to improve accuracy.
|
|
84
|
+
- Not suitable for large storage systems or investment decisions.
|
|
85
|
+
|
|
86
|
+
- **Aggregated Mode**
|
|
87
|
+
- Automatically generates typical periods using [TSAM](https://github.com/FZJ-IEK3-VSA/tsam).
|
|
88
|
+
- Balances speed and accuracy, making it ideal for large-scale simulations.
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
## 🏗️ Architecture
|
|
92
|
+
|
|
93
|
+
- **Minimal coupling to Pyomo**
|
|
94
|
+
- Included independent module is used to organize variables and equations, independently of a specific modeling language.
|
|
95
|
+
- While currently only working with [Pyomo](http://www.pyomo.org/), flixOpt is designed to work with different modeling languages with minor modifications ([cvxpy](https://www.cvxpy.org)).
|
|
96
|
+
|
|
97
|
+
- **File-based Post-Processing Unit**
|
|
98
|
+
- Results are saved to .json and .yaml files for easy access and analysis anytime.
|
|
99
|
+
- Internal plotting functions utilizing matplotlib, plotly and pandas simplify results visualization and reporting.
|
|
100
|
+
|
|
101
|
+

|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 🛠️ Solver Integration
|
|
106
|
+
|
|
107
|
+
By default, flixOpt uses the open-source solver [HiGHS](https://highs.dev/) which is installed by default. However, it is compatible with additional solvers such as:
|
|
108
|
+
|
|
109
|
+
- [CBC](https://github.com/coin-or/Cbc)
|
|
110
|
+
- [GLPK](https://www.gnu.org/software/glpk/)
|
|
111
|
+
- [Gurobi](https://www.gurobi.com/)
|
|
112
|
+
- [CPLEX](https://www.ibm.com/analytics/cplex-optimizer)
|
|
113
|
+
|
|
114
|
+
Executables can be found for example [here for CBC](https://portal.ampl.com/dl/open/cbc/) and [here for GLPK](https://sourceforge.net/projects/winglpk/) (Windows: You have to put solver-executables to the PATH-variable)
|
|
115
|
+
|
|
116
|
+
For detailed licensing and installation instructions, refer to the respective solver documentation.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 📖 Citation
|
|
121
|
+
|
|
122
|
+
If you use flixOpt in your research or project, please cite the following:
|
|
123
|
+
|
|
124
|
+
- **Main Citation:** [DOI:10.18086/eurosun.2022.04.07](https://doi.org/10.18086/eurosun.2022.04.07)
|
|
125
|
+
- **Short Overview:** [DOI:10.13140/RG.2.2.14948.24969](https://doi.org/10.13140/RG.2.2.14948.24969)
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 🔧 Development and Testing
|
|
130
|
+
|
|
131
|
+
Run the tests using:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
python -m unittest discover -s tests
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This script shows how to use the flixOpt framework to model a super minimalistic energy system.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from rich.pretty import pprint
|
|
7
|
+
|
|
8
|
+
import flixOpt as fx
|
|
9
|
+
|
|
10
|
+
if __name__ == '__main__':
|
|
11
|
+
# --- Define Thermal Load Profile ---
|
|
12
|
+
# Load profile (e.g., kW) for heating demand over time
|
|
13
|
+
thermal_load_profile = np.array([30, 0, 20])
|
|
14
|
+
datetime_series = fx.create_datetime_array('2020-01-01', 3, 'h')
|
|
15
|
+
|
|
16
|
+
# --- Define Energy Buses ---
|
|
17
|
+
# These represent the different energy carriers in the system
|
|
18
|
+
electricity_bus = fx.Bus('Electricity')
|
|
19
|
+
heat_bus = fx.Bus('District Heating')
|
|
20
|
+
fuel_bus = fx.Bus('Natural Gas')
|
|
21
|
+
|
|
22
|
+
# --- Define Objective Effect (Cost) ---
|
|
23
|
+
# Cost effect representing the optimization objective (minimizing costs)
|
|
24
|
+
cost_effect = fx.Effect('costs', '€', 'Cost', is_standard=True, is_objective=True)
|
|
25
|
+
|
|
26
|
+
# --- Define Flow System Components ---
|
|
27
|
+
# Boiler component with thermal output (heat) and fuel input (gas)
|
|
28
|
+
boiler = fx.linear_converters.Boiler(
|
|
29
|
+
'Boiler',
|
|
30
|
+
eta=0.5,
|
|
31
|
+
Q_th=fx.Flow(label='Thermal Output', bus=heat_bus, size=50),
|
|
32
|
+
Q_fu=fx.Flow(label='Fuel Input', bus=fuel_bus),
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# Heat load component with a fixed thermal demand profile
|
|
36
|
+
heat_load = fx.Sink(
|
|
37
|
+
'Heat Demand',
|
|
38
|
+
sink=fx.Flow(label='Thermal Load', bus=heat_bus, size=1, fixed_relative_profile=thermal_load_profile),
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# Gas source component with cost-effect per flow hour
|
|
42
|
+
gas_source = fx.Source(
|
|
43
|
+
'Natural Gas Tariff',
|
|
44
|
+
source=fx.Flow(label='Gas Flow', bus=fuel_bus, size=1000, effects_per_flow_hour=0.04), # 0.04 €/kWh
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# --- Build the Flow System ---
|
|
48
|
+
# Add all components and effects to the system
|
|
49
|
+
flow_system = fx.FlowSystem(datetime_series)
|
|
50
|
+
flow_system.add_elements(cost_effect, boiler, heat_load, gas_source)
|
|
51
|
+
|
|
52
|
+
# --- Define and Run Calculation ---
|
|
53
|
+
calculation = fx.FullCalculation('Simulation1', flow_system)
|
|
54
|
+
calculation.do_modeling()
|
|
55
|
+
|
|
56
|
+
# --- Solve the Calculation and Save Results ---
|
|
57
|
+
calculation.solve(fx.solvers.HighsSolver(), save_results=True)
|
|
58
|
+
|
|
59
|
+
# --- Load and Analyze Results ---
|
|
60
|
+
# Load results and plot the operation of the District Heating Bus
|
|
61
|
+
results = fx.results.CalculationResults(calculation.name, folder='results')
|
|
62
|
+
results.plot_operation('District Heating', 'area')
|
|
63
|
+
|
|
64
|
+
# Print results to the console. Check Results in file or perform more plotting
|
|
65
|
+
pprint(calculation.results())
|
|
66
|
+
pprint('Look into .yaml and .json file for results')
|
|
67
|
+
pprint(calculation.system_model.main_results)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""
|
|
2
|
+
THis script shows how to use the flixOpt framework to model a simple energy system.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from rich.pretty import pprint # Used for pretty printing
|
|
7
|
+
|
|
8
|
+
import flixOpt as fx
|
|
9
|
+
|
|
10
|
+
if __name__ == '__main__':
|
|
11
|
+
# --- Create Time Series Data ---
|
|
12
|
+
# Heat demand profile (e.g., kW) over time and corresponding power prices
|
|
13
|
+
heat_demand_per_h = np.array([30, 0, 90, 110, 110, 20, 20, 20, 20])
|
|
14
|
+
power_prices = 1 / 1000 * np.array([80, 80, 80, 80, 80, 80, 80, 80, 80])
|
|
15
|
+
|
|
16
|
+
# Create datetime array starting from '2020-01-01' for the given time period
|
|
17
|
+
time_series = fx.create_datetime_array('2020-01-01', len(heat_demand_per_h))
|
|
18
|
+
|
|
19
|
+
# --- Define Energy Buses ---
|
|
20
|
+
# These represent nodes, where the used medias are balanced (electricity, heat, and gas)
|
|
21
|
+
Strom, Fernwaerme, Gas = fx.Bus(label='Strom'), fx.Bus(label='Fernwärme'), fx.Bus(label='Gas')
|
|
22
|
+
|
|
23
|
+
# --- Define Effects (Objective and CO2 Emissions) ---
|
|
24
|
+
# Cost effect: used as the optimization objective --> minimizing costs
|
|
25
|
+
costs = fx.Effect(
|
|
26
|
+
label='costs',
|
|
27
|
+
unit='€',
|
|
28
|
+
description='Kosten',
|
|
29
|
+
is_standard=True, # standard effect: no explicit value needed for costs
|
|
30
|
+
is_objective=True, # Minimizing costs as the optimization objective
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# CO2 emissions effect with an associated cost impact
|
|
34
|
+
CO2 = fx.Effect(
|
|
35
|
+
label='CO2',
|
|
36
|
+
unit='kg',
|
|
37
|
+
description='CO2_e-Emissionen',
|
|
38
|
+
specific_share_to_other_effects_operation={costs: 0.2},
|
|
39
|
+
maximum_operation_per_hour=1000, # Max CO2 emissions per hour
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# --- Define Flow System Components ---
|
|
43
|
+
# Boiler: Converts fuel (gas) into thermal energy (heat)
|
|
44
|
+
boiler = fx.linear_converters.Boiler(
|
|
45
|
+
label='Boiler',
|
|
46
|
+
eta=0.5,
|
|
47
|
+
Q_th=fx.Flow(label='Q_th', bus=Fernwaerme, size=50, relative_minimum=0.1, relative_maximum=1),
|
|
48
|
+
Q_fu=fx.Flow(label='Q_fu', bus=Gas),
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Combined Heat and Power (CHP): Generates both electricity and heat from fuel
|
|
52
|
+
chp = fx.linear_converters.CHP(
|
|
53
|
+
label='CHP',
|
|
54
|
+
eta_th=0.5,
|
|
55
|
+
eta_el=0.4,
|
|
56
|
+
P_el=fx.Flow('P_el', bus=Strom, size=60, relative_minimum=5 / 60),
|
|
57
|
+
Q_th=fx.Flow('Q_th', bus=Fernwaerme),
|
|
58
|
+
Q_fu=fx.Flow('Q_fu', bus=Gas),
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Storage: Energy storage system with charging and discharging capabilities
|
|
62
|
+
storage = fx.Storage(
|
|
63
|
+
label='Storage',
|
|
64
|
+
charging=fx.Flow('Q_th_load', bus=Fernwaerme, size=1000),
|
|
65
|
+
discharging=fx.Flow('Q_th_unload', bus=Fernwaerme, size=1000),
|
|
66
|
+
capacity_in_flow_hours=fx.InvestParameters(fix_effects=20, fixed_size=30, optional=False),
|
|
67
|
+
initial_charge_state=0, # Initial storage state: empty
|
|
68
|
+
relative_maximum_charge_state=1 / 100 * np.array([80, 70, 80, 80, 80, 80, 80, 80, 80, 80]),
|
|
69
|
+
eta_charge=0.9,
|
|
70
|
+
eta_discharge=1, # Efficiency factors for charging/discharging
|
|
71
|
+
relative_loss_per_hour=0.08, # 8% loss per hour. Absolute loss depends on current charge state
|
|
72
|
+
prevent_simultaneous_charge_and_discharge=True, # Prevent charging and discharging at the same time
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# Heat Demand Sink: Represents a fixed heat demand profile
|
|
76
|
+
heat_sink = fx.Sink(
|
|
77
|
+
label='Heat Demand',
|
|
78
|
+
sink=fx.Flow(label='Q_th_Last', bus=Fernwaerme, size=1, fixed_relative_profile=heat_demand_per_h),
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Gas Source: Gas tariff source with associated costs and CO2 emissions
|
|
82
|
+
gas_source = fx.Source(
|
|
83
|
+
label='Gastarif',
|
|
84
|
+
source=fx.Flow(label='Q_Gas', bus=Gas, size=1000, effects_per_flow_hour={costs: 0.04, CO2: 0.3}),
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
# Power Sink: Represents the export of electricity to the grid
|
|
88
|
+
power_sink = fx.Sink(
|
|
89
|
+
label='Einspeisung', sink=fx.Flow(label='P_el', bus=Strom, effects_per_flow_hour=-1 * power_prices)
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# --- Build the Flow System ---
|
|
93
|
+
# Create the flow system and add all defined components and effects
|
|
94
|
+
flow_system = fx.FlowSystem(time_series=time_series)
|
|
95
|
+
flow_system.add_elements(costs, CO2, boiler, storage, chp, heat_sink, gas_source, power_sink)
|
|
96
|
+
|
|
97
|
+
# Visualize the flow system for validation purposes
|
|
98
|
+
flow_system.visualize_network()
|
|
99
|
+
|
|
100
|
+
# --- Define and Run Calculation ---
|
|
101
|
+
# Create a calculation object to model the Flow System
|
|
102
|
+
calculation = fx.FullCalculation(name='Sim1', flow_system=flow_system)
|
|
103
|
+
calculation.do_modeling() # Translate the model to a solvable form, creating equations and Variables
|
|
104
|
+
|
|
105
|
+
# --- Solve the Calculation and Save Results ---
|
|
106
|
+
calculation.solve(fx.solvers.HighsSolver(), save_results=True)
|
|
107
|
+
|
|
108
|
+
# --- Load and Analyze Results ---
|
|
109
|
+
# Load the results and plot the operation of the District Heating Bus
|
|
110
|
+
results = fx.results.CalculationResults(calculation.name, folder='results')
|
|
111
|
+
results.plot_operation('Fernwärme', 'area')
|
|
112
|
+
results.plot_storage('Storage')
|
|
113
|
+
results.plot_operation('Fernwärme', 'bar')
|
|
114
|
+
results.plot_operation('Fernwärme', 'line')
|
|
115
|
+
results.plot_operation('CHP__Q_th', 'line')
|
|
116
|
+
results.plot_operation('CHP__Q_th', 'heatmap')
|
|
117
|
+
|
|
118
|
+
# Convert the results for the storage component to a dataframe and display
|
|
119
|
+
results.to_dataframe('Storage')
|
|
120
|
+
pprint(results.all_results)
|