flixopt 2.1.1__tar.gz → 2.1.3__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-2.1.3/.github/CONTRIBUTING.md +85 -0
- flixopt-2.1.3/.github/ISSUE_TEMPLATE/bug_report.yml +81 -0
- flixopt-2.1.3/.github/ISSUE_TEMPLATE/config.yml +8 -0
- flixopt-2.1.3/.github/ISSUE_TEMPLATE/feature_request.yml +88 -0
- flixopt-2.1.3/.github/pull_request_template.md +20 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/.github/workflows/python-app.yaml +78 -7
- flixopt-2.1.3/CHANGELOG.md +87 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/PKG-INFO +29 -29
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/SUMMARY.md +1 -1
- {flixopt-2.1.1 → flixopt-2.1.3}/examples/02_Complex/complex_example_results.py +5 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/components.py +1 -1
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/core.py +6 -2
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/effects.py +1 -1
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt.egg-info/PKG-INFO +29 -29
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt.egg-info/SOURCES.txt +7 -8
- flixopt-2.1.3/flixopt.egg-info/requires.txt +39 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt.egg-info/top_level.txt +0 -1
- {flixopt-2.1.1 → flixopt-2.1.3}/mkdocs.yml +3 -2
- {flixopt-2.1.1 → flixopt-2.1.3}/pyproject.toml +40 -31
- flixopt-2.1.3/scripts/extract_release_notes.py +45 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_storage.py +1 -1
- flixopt-2.1.1/.github/workflows/deploy-docs.yaml +0 -33
- flixopt-2.1.1/docs/release-notes/_template.txt +0 -32
- flixopt-2.1.1/docs/release-notes/index.md +0 -7
- flixopt-2.1.1/docs/release-notes/v2.0.0.md +0 -93
- flixopt-2.1.1/docs/release-notes/v2.0.1.md +0 -12
- flixopt-2.1.1/docs/release-notes/v2.1.0.md +0 -31
- flixopt-2.1.1/docs/release-notes/v2.1.1.md +0 -11
- flixopt-2.1.1/flixopt.egg-info/requires.txt +0 -37
- flixopt-2.1.1/site/release-notes/_template.txt +0 -32
- {flixopt-2.1.1 → flixopt-2.1.3}/.gitignore +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/LICENSE +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/README.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/contribute.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/examples/00-Minimal Example.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/examples/01-Basic Example.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/examples/02-Complex Example.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/examples/03-Calculation Modes.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/examples/index.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/faq/contribute.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/faq/index.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/getting-started.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/images/architecture_flixOpt-pre2.0.0.png +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/images/architecture_flixOpt.png +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/images/flixopt-icon.svg +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/index.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/javascripts/mathjax.js +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/Mathematical Notation/Bus.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/Mathematical Notation/Effects, Penalty & Objective.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/Mathematical Notation/Flow.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/Mathematical Notation/LinearConverter.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/Mathematical Notation/Piecewise.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/Mathematical Notation/Storage.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/Mathematical Notation/index.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/Mathematical Notation/others.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/index.md +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/examples/00_Minmal/minimal_example.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/examples/01_Simple/simple_example.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/examples/02_Complex/complex_example.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/examples/03_Calculation_types/Zeitreihen2020.csv +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/examples/03_Calculation_types/example_calculation_types.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/__init__.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/aggregation.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/calculation.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/commons.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/config.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/config.yaml +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/elements.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/features.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/flow_system.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/interface.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/io.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/linear_converters.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/plotting.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/results.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/solvers.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/structure.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/utils.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/flixopt.egg-info/dependency_links.txt +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/pics/architecture_flixOpt-pre2.0.0.png +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/pics/architecture_flixOpt.png +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/pics/flixOpt_plotting.jpg +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/pics/flixopt-icon.svg +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/pics/pics.pptx +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/scripts/gen_ref_pages.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/setup.cfg +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/__init__.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/conftest.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/ressources/Zeitreihen2020.csv +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/run_all_tests.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_bus.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_component.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_dataconverter.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_effect.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_examples.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_flow.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_functional.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_integration.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_io.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_linear_converter.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_on_hours_computation.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_plots.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_results_plots.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_timeseries.py +0 -0
- {flixopt-2.1.1 → flixopt-2.1.3}/tests/todos.txt +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Contributing to FlixOpt
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing to FlixOpt! 🚀
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
1. **Fork & Clone**
|
|
8
|
+
```bash
|
|
9
|
+
git clone https://github.com/yourusername/flixopt.git
|
|
10
|
+
cd flixopt
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. **Install for Development**
|
|
14
|
+
```bash
|
|
15
|
+
pip install -e ".[full]"
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
3. **Make Changes & Submit PR**
|
|
19
|
+
```bash
|
|
20
|
+
git checkout -b feature/your-change
|
|
21
|
+
# Make your changes
|
|
22
|
+
git commit -m "Add: description of changes"
|
|
23
|
+
git push origin feature/your-change
|
|
24
|
+
# Create Pull Request on GitHub
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## How to Contribute
|
|
28
|
+
|
|
29
|
+
### 🐛 **Found a Bug?**
|
|
30
|
+
Use our [bug report template](https://github.com/flixOpt/flixopt/issues/new?template=bug_report.yml) with:
|
|
31
|
+
- Minimal code example
|
|
32
|
+
- FlixOpt version, Python version, solver used
|
|
33
|
+
- Expected vs actual behavior
|
|
34
|
+
|
|
35
|
+
### ✨ **Have a Feature Idea?**
|
|
36
|
+
Use our [feature request template](https://github.com/flixOpt/flixopt/issues/new?template=feature_request.yml) with:
|
|
37
|
+
- Clear energy system use case
|
|
38
|
+
- Specific examples of what you want to model
|
|
39
|
+
|
|
40
|
+
### ❓ **Need Help?**
|
|
41
|
+
- Check the [documentation](https://flixopt.github.io/flixopt/latest/) first
|
|
42
|
+
- Search [existing issues](https://github.com/flixOpt/flixopt/issues)
|
|
43
|
+
- Start a [discussion](https://github.com/flixOpt/flixopt/discussions)
|
|
44
|
+
|
|
45
|
+
## Code Guidelines
|
|
46
|
+
|
|
47
|
+
- **Style**: Follow PEP 8, use descriptive names
|
|
48
|
+
- **Documentation**: Add docstrings with units (kW, kWh, etc.) if applicable
|
|
49
|
+
- **Energy Focus**: Use energy domain terminology consistently
|
|
50
|
+
- **Testing**: Test with different solvers when applicable
|
|
51
|
+
|
|
52
|
+
### Example
|
|
53
|
+
```python
|
|
54
|
+
def create_storage(
|
|
55
|
+
label: str,
|
|
56
|
+
capacity_kwh: float,
|
|
57
|
+
charging_power_kw: float
|
|
58
|
+
) -> Storage:
|
|
59
|
+
"""
|
|
60
|
+
Create a battery storage component.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
label: Unique identifier
|
|
64
|
+
capacity_kwh: Storage capacity [kWh]
|
|
65
|
+
charging_power_kw: Maximum charging power [kW]
|
|
66
|
+
"""
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## What We Welcome
|
|
70
|
+
|
|
71
|
+
- 🔧 New energy components (batteries, heat pumps, etc.)
|
|
72
|
+
- 📚 Documentation improvements
|
|
73
|
+
- 🐛 Bug fixes
|
|
74
|
+
- 🧪 Test cases
|
|
75
|
+
- 💡 Energy system examples
|
|
76
|
+
|
|
77
|
+
## Questions?
|
|
78
|
+
|
|
79
|
+
- 📖 [Documentation](https://flixopt.github.io/flixopt/latest/)
|
|
80
|
+
- 💬 [Discussions](https://github.com/flixOpt/flixopt/discussions)
|
|
81
|
+
- 📧 Contact maintainers (see README)
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
**Every contribution helps advance sustainable energy solutions! 🌱⚡**
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
name: 🐛 Bug Report
|
|
2
|
+
description: Report a bug in flixopt
|
|
3
|
+
title: "[BUG] "
|
|
4
|
+
labels: ["type: bug"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for taking the time to fill out this bug report!
|
|
10
|
+
- type: checkboxes
|
|
11
|
+
id: checks
|
|
12
|
+
attributes:
|
|
13
|
+
label: Version Checks (indicate both or one)
|
|
14
|
+
options:
|
|
15
|
+
- label: >
|
|
16
|
+
I have confirmed this bug exists on the latest
|
|
17
|
+
[release](https://github.com/flixOpt/flixopt/releases) of FlixOpt.
|
|
18
|
+
- label: >
|
|
19
|
+
I have confirmed this bug exists on the current
|
|
20
|
+
[`main`](https://github.com/flixOpt/flixopt/tree/main) branch of FlixOpt.
|
|
21
|
+
- type: textarea
|
|
22
|
+
id: problem
|
|
23
|
+
attributes:
|
|
24
|
+
label: Issue Description
|
|
25
|
+
description: >
|
|
26
|
+
Please provide a description of the issue.
|
|
27
|
+
validations:
|
|
28
|
+
required: true
|
|
29
|
+
- type: textarea
|
|
30
|
+
id: example
|
|
31
|
+
validations:
|
|
32
|
+
required: true
|
|
33
|
+
attributes:
|
|
34
|
+
label: Reproducible Example
|
|
35
|
+
description: >
|
|
36
|
+
Please provide a minimal reproducible example. See how to [craft minimal bug reports](https://matthewrocklin.com/minimal-bug-reports).
|
|
37
|
+
placeholder: >
|
|
38
|
+
import flixopt as fx
|
|
39
|
+
|
|
40
|
+
# Create simple energy system that reproduces the bug
|
|
41
|
+
timesteps = pd.date_range('2024-01-01', periods=24, freq='h')
|
|
42
|
+
flow_system = fx.FlowSystem(timesteps)
|
|
43
|
+
|
|
44
|
+
# Add your components here...
|
|
45
|
+
render: python
|
|
46
|
+
- type: textarea
|
|
47
|
+
id: expected-behavior
|
|
48
|
+
validations:
|
|
49
|
+
required: true
|
|
50
|
+
attributes:
|
|
51
|
+
label: Expected Behavior
|
|
52
|
+
description: >
|
|
53
|
+
Please describe or show a code example of the expected behavior.
|
|
54
|
+
- type: dropdown
|
|
55
|
+
id: solver
|
|
56
|
+
attributes:
|
|
57
|
+
label: Solver Used
|
|
58
|
+
description: Which solver were you using when the bug occurred?
|
|
59
|
+
options:
|
|
60
|
+
- HiGHS (default)
|
|
61
|
+
- Gurobi
|
|
62
|
+
- CPLEX
|
|
63
|
+
- GLPK
|
|
64
|
+
- Other (please specify in description)
|
|
65
|
+
validations:
|
|
66
|
+
required: true
|
|
67
|
+
- type: textarea
|
|
68
|
+
id: version
|
|
69
|
+
attributes:
|
|
70
|
+
label: Installed Versions
|
|
71
|
+
description: >
|
|
72
|
+
Please share information on your environment. Paste the output below.
|
|
73
|
+
For conda: `conda env export` and for pip: `pip freeze`.
|
|
74
|
+
value: >
|
|
75
|
+
<details>
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
Replace this with your environment info
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
</details>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: ❓ Questions & Discussion
|
|
4
|
+
url: https://github.com/flixOpt/flixopt/discussions
|
|
5
|
+
about: Ask questions and discuss with the community
|
|
6
|
+
- name: 📖 Documentation
|
|
7
|
+
url: https://flixopt.github.io/flixopt/latest/
|
|
8
|
+
about: Check our documentation for guides and examples
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
name: Feature Request
|
|
2
|
+
description: Suggest a new feature or enhancement for FlixOpt.
|
|
3
|
+
title: "[FEATURE] "
|
|
4
|
+
labels: ["type: feature"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for suggesting a new feature! Please provide as much detail as possible.
|
|
10
|
+
- type: checkboxes
|
|
11
|
+
id: checks
|
|
12
|
+
attributes:
|
|
13
|
+
label: Prerequisite Checks
|
|
14
|
+
options:
|
|
15
|
+
- label: >
|
|
16
|
+
I have searched the [existing issues](https://github.com/flixOpt/flixopt/issues)
|
|
17
|
+
and confirmed this feature doesn't already exist.
|
|
18
|
+
- label: >
|
|
19
|
+
I have checked the [documentation](https://flixopt.github.io/flixopt/latest/)
|
|
20
|
+
to ensure this feature isn't already available.
|
|
21
|
+
- type: textarea
|
|
22
|
+
id: problem
|
|
23
|
+
attributes:
|
|
24
|
+
label: Is your feature request related to a problem?
|
|
25
|
+
description: >
|
|
26
|
+
A clear and concise description of what the problem is.
|
|
27
|
+
placeholder: >
|
|
28
|
+
I'm always frustrated when modeling [specific energy system scenario]...
|
|
29
|
+
- type: textarea
|
|
30
|
+
id: solution
|
|
31
|
+
validations:
|
|
32
|
+
required: true
|
|
33
|
+
attributes:
|
|
34
|
+
label: Describe the solution you'd like
|
|
35
|
+
description: >
|
|
36
|
+
A clear and concise description of what you want to happen.
|
|
37
|
+
placeholder: >
|
|
38
|
+
I would like to be able to model [specific component/feature]...
|
|
39
|
+
- type: textarea
|
|
40
|
+
id: use-case
|
|
41
|
+
validations:
|
|
42
|
+
required: true
|
|
43
|
+
attributes:
|
|
44
|
+
label: Energy System Use Case
|
|
45
|
+
description: >
|
|
46
|
+
Describe your specific energy system modeling scenario and how this feature would help.
|
|
47
|
+
placeholder: >
|
|
48
|
+
I'm modeling a district heating system with seasonal thermal storage and need to...
|
|
49
|
+
- type: textarea
|
|
50
|
+
id: example
|
|
51
|
+
attributes:
|
|
52
|
+
label: Desired Code Example (optional)
|
|
53
|
+
description: >
|
|
54
|
+
If possible, show how you would like to use this feature in code.
|
|
55
|
+
placeholder: >
|
|
56
|
+
# Example of how the new feature might work
|
|
57
|
+
thermal_storage = fx.SeasonalStorage(
|
|
58
|
+
label='seasonal_storage',
|
|
59
|
+
capacity_mwh=1000,
|
|
60
|
+
efficiency=0.95
|
|
61
|
+
)
|
|
62
|
+
render: python
|
|
63
|
+
- type: dropdown
|
|
64
|
+
id: component-type
|
|
65
|
+
attributes:
|
|
66
|
+
label: Component Category (if applicable)
|
|
67
|
+
description: What type of energy system component does this relate to?
|
|
68
|
+
options:
|
|
69
|
+
- Storage (batteries, thermal storage, etc.)
|
|
70
|
+
- Generation (PV, wind, CHP, etc.)
|
|
71
|
+
- Conversion (heat pumps, boilers, etc.)
|
|
72
|
+
- Network/Grid (transmission, distribution)
|
|
73
|
+
- Optimization/Calculation (algorithms, solvers)
|
|
74
|
+
- Data/Input handling
|
|
75
|
+
- Results/Output
|
|
76
|
+
- Other
|
|
77
|
+
- type: textarea
|
|
78
|
+
id: alternatives
|
|
79
|
+
attributes:
|
|
80
|
+
label: Alternatives considered
|
|
81
|
+
description: >
|
|
82
|
+
Describe any alternative solutions or workarounds you've considered.
|
|
83
|
+
- type: textarea
|
|
84
|
+
id: additional-context
|
|
85
|
+
attributes:
|
|
86
|
+
label: Additional context
|
|
87
|
+
description: >
|
|
88
|
+
Add any other context, research papers, or examples about the feature request here.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
## Description
|
|
2
|
+
Brief description of the changes in this PR.
|
|
3
|
+
|
|
4
|
+
## Type of Change
|
|
5
|
+
- [ ] Bug fix
|
|
6
|
+
- [ ] New feature
|
|
7
|
+
- [ ] Documentation update
|
|
8
|
+
- [ ] Code refactoring
|
|
9
|
+
|
|
10
|
+
## Related Issues
|
|
11
|
+
Closes #(issue number)
|
|
12
|
+
|
|
13
|
+
## Testing
|
|
14
|
+
- [ ] I have tested my changes
|
|
15
|
+
- [ ] Existing tests still pass
|
|
16
|
+
|
|
17
|
+
## Checklist
|
|
18
|
+
- [ ] My code follows the project style
|
|
19
|
+
- [ ] I have updated documentation if needed
|
|
20
|
+
- [ ] I have added tests for new functionality (if applicable)
|
|
@@ -56,12 +56,49 @@ jobs:
|
|
|
56
56
|
- name: Run tests
|
|
57
57
|
run: pytest -v -p no:warnings
|
|
58
58
|
|
|
59
|
+
create-release:
|
|
60
|
+
name: Create Release with Changelog
|
|
61
|
+
runs-on: ubuntu-22.04
|
|
62
|
+
needs: [test]
|
|
63
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
64
|
+
|
|
65
|
+
steps:
|
|
66
|
+
- name: Checkout repository
|
|
67
|
+
uses: actions/checkout@v4
|
|
68
|
+
with:
|
|
69
|
+
fetch-depth: 0
|
|
70
|
+
|
|
71
|
+
- name: Set up Python
|
|
72
|
+
uses: actions/setup-python@v4
|
|
73
|
+
with:
|
|
74
|
+
python-version: "3.11"
|
|
75
|
+
|
|
76
|
+
- name: Sync changelog to docs
|
|
77
|
+
run: |
|
|
78
|
+
cp CHANGELOG.md docs/changelog.md
|
|
79
|
+
echo "✅ Synced changelog to docs"
|
|
80
|
+
|
|
81
|
+
- name: Extract release notes
|
|
82
|
+
run: |
|
|
83
|
+
VERSION=${GITHUB_REF#refs/tags/v}
|
|
84
|
+
echo "Extracting release notes for version: $VERSION"
|
|
85
|
+
python scripts/extract_release_notes.py $VERSION > current_release_notes.md
|
|
86
|
+
|
|
87
|
+
- name: Create GitHub Release
|
|
88
|
+
uses: softprops/action-gh-release@v1
|
|
89
|
+
with:
|
|
90
|
+
body_path: current_release_notes.md
|
|
91
|
+
draft: false
|
|
92
|
+
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
|
|
93
|
+
env:
|
|
94
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
95
|
+
|
|
59
96
|
publish-testpypi:
|
|
60
97
|
name: Publish to TestPyPI
|
|
61
98
|
runs-on: ubuntu-22.04
|
|
62
|
-
needs: [test] #
|
|
63
|
-
if: github.event_name == '
|
|
64
|
-
|
|
99
|
+
needs: [test, create-release] # Run after tests and release creation
|
|
100
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') # Only on tag push
|
|
101
|
+
|
|
65
102
|
steps:
|
|
66
103
|
- name: Checkout repository
|
|
67
104
|
uses: actions/checkout@v4
|
|
@@ -86,7 +123,7 @@ jobs:
|
|
|
86
123
|
env:
|
|
87
124
|
TWINE_USERNAME: __token__
|
|
88
125
|
TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
|
|
89
|
-
|
|
126
|
+
|
|
90
127
|
- name: Test install from TestPyPI
|
|
91
128
|
run: |
|
|
92
129
|
# Create a temporary environment to test installation
|
|
@@ -104,8 +141,8 @@ jobs:
|
|
|
104
141
|
publish-pypi:
|
|
105
142
|
name: Publish to PyPI
|
|
106
143
|
runs-on: ubuntu-22.04
|
|
107
|
-
needs: [
|
|
108
|
-
if: github.event_name == '
|
|
144
|
+
needs: [publish-testpypi] # Only run after TestPyPI publish succeeds
|
|
145
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') # Only on tag push
|
|
109
146
|
|
|
110
147
|
steps:
|
|
111
148
|
- name: Checkout repository
|
|
@@ -144,4 +181,38 @@ jobs:
|
|
|
144
181
|
# Install from PyPI
|
|
145
182
|
pip install $PACKAGE_NAME
|
|
146
183
|
# Basic import test
|
|
147
|
-
python -c "import flixopt; print('PyPI installation successful!')"
|
|
184
|
+
python -c "import flixopt; print('PyPI installation successful!')"
|
|
185
|
+
|
|
186
|
+
deploy-docs:
|
|
187
|
+
name: Deploy Documentation
|
|
188
|
+
runs-on: ubuntu-22.04
|
|
189
|
+
needs: [publish-pypi] # Deploy docs after successful PyPI publishing
|
|
190
|
+
if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, 'alpha') && !contains(github.ref, 'beta') && !contains(github.ref, 'rc')
|
|
191
|
+
|
|
192
|
+
steps:
|
|
193
|
+
- name: Checkout repository
|
|
194
|
+
uses: actions/checkout@v4
|
|
195
|
+
with:
|
|
196
|
+
fetch-depth: 0 # Fetch all history for proper versioning
|
|
197
|
+
|
|
198
|
+
- name: Set up Python
|
|
199
|
+
uses: actions/setup-python@v4
|
|
200
|
+
with:
|
|
201
|
+
python-version: "3.11"
|
|
202
|
+
|
|
203
|
+
- name: Install documentation dependencies
|
|
204
|
+
run: |
|
|
205
|
+
python -m pip install --upgrade pip
|
|
206
|
+
pip install -e ".[docs]"
|
|
207
|
+
|
|
208
|
+
- name: Configure Git Credentials
|
|
209
|
+
run: |
|
|
210
|
+
git config user.name github-actions[bot]
|
|
211
|
+
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
|
|
212
|
+
|
|
213
|
+
- name: Deploy docs
|
|
214
|
+
run: |
|
|
215
|
+
VERSION=${GITHUB_REF#refs/tags/v}
|
|
216
|
+
echo "Deploying docs after successful PyPI publish: $VERSION"
|
|
217
|
+
mike deploy --push --update-aliases $VERSION latest
|
|
218
|
+
mike set-default --push latest
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [2.1.3] - 2025-07-08
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Using `Effect.maximum_operation_per_hour` raised an error, needing an extra timestep. This has been fixed.
|
|
14
|
+
|
|
15
|
+
## [2.1.2] - 2025-06-14
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- Storage losses per hour where not calculated correctly, as mentioned by @brokenwings01. This might have lead to issues with modeling large losses and long timesteps.
|
|
19
|
+
- Old implementation: $c(\text{t}_{i}) \cdot (1-\dot{\text{c}}_\text{rel,loss}(\text{t}_i)) \cdot \Delta \text{t}_{i}$
|
|
20
|
+
- Correct implementation: $c(\text{t}_{i}) \cdot (1-\dot{\text{c}}_\text{rel,loss}(\text{t}_i)) ^{\Delta \text{t}_{i}}$
|
|
21
|
+
|
|
22
|
+
### Known issues
|
|
23
|
+
- Just to mention: Plotly >= 6 may raise errors if "nbformat" is not installed. We pinned plotly to <6, but this may be fixed in the future.
|
|
24
|
+
|
|
25
|
+
## [2.1.1] - 2025-05-08
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- Fixed bug in the `_ElementResults.constraints` not returning the constraints but rather the variables
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
- Improved docstring and tests
|
|
32
|
+
|
|
33
|
+
## [2.1.0] - 2025-04-11
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
- Python 3.13 support added
|
|
37
|
+
- Logger warning if relative_minimum is used without on_off_parameters in Flow
|
|
38
|
+
- Greatly improved internal testing infrastructure by leveraging linopy's testing framework
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
- Fixed the lower bound of `flow_rate` when using optional investments without OnOffParameters
|
|
42
|
+
- Fixed bug that prevented divest effects from working
|
|
43
|
+
- Added lower bounds of 0 to two unbounded vars (numerical improvement)
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
- **BREAKING**: Restructured the modeling of the On/Off state of Flows or Components
|
|
47
|
+
- Variable renaming: `...|consecutive_on_hours` → `...|ConsecutiveOn|hours`
|
|
48
|
+
- Variable renaming: `...|consecutive_off_hours` → `...|ConsecutiveOff|hours`
|
|
49
|
+
- Constraint renaming: `...|consecutive_on_hours_con1` → `...|ConsecutiveOn|con1`
|
|
50
|
+
- Similar pattern for all consecutive on/off constraints
|
|
51
|
+
|
|
52
|
+
## [2.0.1] - 2025-04-10
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
- Logger warning if relative_minimum is used without on_off_parameters in Flow
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
- Replace "|" with "__" in filenames when saving figures (Windows compatibility)
|
|
59
|
+
- Fixed bug that prevented the load factor from working without InvestmentParameters
|
|
60
|
+
|
|
61
|
+
## [2.0.0] - 2025-03-29
|
|
62
|
+
|
|
63
|
+
### Changed
|
|
64
|
+
- **BREAKING**: Complete migration from Pyomo to Linopy optimization framework
|
|
65
|
+
- **BREAKING**: Redesigned data handling to rely on xarray.Dataset throughout the package
|
|
66
|
+
- **BREAKING**: Framework renamed from flixOpt to flixopt (`import flixopt as fx`)
|
|
67
|
+
- **BREAKING**: Results handling completely redesigned with new `CalculationResults` class
|
|
68
|
+
|
|
69
|
+
### Added
|
|
70
|
+
- Full model serialization support - save and restore unsolved Models
|
|
71
|
+
- Enhanced model documentation with YAML export containing human-readable mathematical formulations
|
|
72
|
+
- Extend flixopt models with native linopy language support
|
|
73
|
+
- Full Model Export/Import capabilities via linopy.Model
|
|
74
|
+
- Unified solution exploration through `Calculation.results` attribute
|
|
75
|
+
- Compression support for result files
|
|
76
|
+
- `to_netcdf/from_netcdf` methods for FlowSystem and core components
|
|
77
|
+
- xarray integration for TimeSeries with improved datatypes support
|
|
78
|
+
- Google Style Docstrings throughout the codebase
|
|
79
|
+
|
|
80
|
+
### Fixed
|
|
81
|
+
- Improved infeasible model detection and reporting
|
|
82
|
+
- Enhanced time series management and serialization
|
|
83
|
+
- Reduced file size through improved compression
|
|
84
|
+
|
|
85
|
+
### Removed
|
|
86
|
+
- **BREAKING**: Pyomo dependency (replaced by linopy)
|
|
87
|
+
- Period concepts in time management (simplified to timesteps)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flixopt
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.3
|
|
4
4
|
Summary: Vector based energy and material flow optimization framework in Python.
|
|
5
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
6
|
Maintainer-email: Felix Bumann <felixbumann387@gmail.com>, Peter Stange <peter.stange@tu-dresden.de>
|
|
@@ -22,40 +22,40 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
22
22
|
Requires-Python: >=3.10
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
|
25
|
-
Requires-Dist: numpy
|
|
26
|
-
Requires-Dist:
|
|
27
|
-
Requires-Dist: linopy
|
|
28
|
-
Requires-Dist: netcdf4
|
|
29
|
-
Requires-Dist:
|
|
25
|
+
Requires-Dist: numpy<3,>=1.21.5
|
|
26
|
+
Requires-Dist: pandas<3,>=2.0.0
|
|
27
|
+
Requires-Dist: linopy<0.6.0,>=0.5.1
|
|
28
|
+
Requires-Dist: netcdf4<2,>=1.6.1
|
|
29
|
+
Requires-Dist: PyYAML<7,>=6.0.0
|
|
30
|
+
Requires-Dist: rich>=13.0.0
|
|
31
|
+
Requires-Dist: tomli>=2.0.1; python_version < "3.11"
|
|
30
32
|
Requires-Dist: highspy>=1.5.3
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist:
|
|
33
|
-
Requires-Dist: plotly>=5.15
|
|
34
|
-
Requires-Dist: tomli>=2.0.1
|
|
33
|
+
Requires-Dist: matplotlib<4.0.0,>=3.5.2
|
|
34
|
+
Requires-Dist: plotly<6.0.0,>=5.15.0
|
|
35
35
|
Provides-Extra: dev
|
|
36
|
-
Requires-Dist: pytest; extra == "dev"
|
|
37
|
-
Requires-Dist: ruff; extra == "dev"
|
|
36
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
37
|
+
Requires-Dist: ruff>=0.9.0; extra == "dev"
|
|
38
38
|
Requires-Dist: pyvis==0.3.1; extra == "dev"
|
|
39
|
-
Requires-Dist: tsam
|
|
40
|
-
Requires-Dist: scipy
|
|
41
|
-
Requires-Dist: gurobipy>=10.0; extra == "dev"
|
|
39
|
+
Requires-Dist: tsam<3.0.0,>=2.3.1; extra == "dev"
|
|
40
|
+
Requires-Dist: scipy<2.0.0,>=1.15.1; extra == "dev"
|
|
41
|
+
Requires-Dist: gurobipy>=10.0.0; extra == "dev"
|
|
42
42
|
Provides-Extra: full
|
|
43
43
|
Requires-Dist: pyvis==0.3.1; extra == "full"
|
|
44
|
-
Requires-Dist: tsam
|
|
45
|
-
Requires-Dist: scipy
|
|
46
|
-
Requires-Dist: streamlit
|
|
47
|
-
Requires-Dist: gurobipy>=10.0; extra == "full"
|
|
44
|
+
Requires-Dist: tsam<3.0.0,>=2.3.1; extra == "full"
|
|
45
|
+
Requires-Dist: scipy<2.0.0,>=1.15.1; extra == "full"
|
|
46
|
+
Requires-Dist: streamlit<2.0.0,>=1.44.0; extra == "full"
|
|
47
|
+
Requires-Dist: gurobipy>=10.0.0; extra == "full"
|
|
48
48
|
Provides-Extra: docs
|
|
49
|
-
Requires-Dist: mkdocs-material
|
|
50
|
-
Requires-Dist: mkdocstrings-python; extra == "docs"
|
|
51
|
-
Requires-Dist: mkdocs-table-reader-plugin; extra == "docs"
|
|
52
|
-
Requires-Dist: mkdocs-gen-files; extra == "docs"
|
|
53
|
-
Requires-Dist: mkdocs-include-markdown-plugin; extra == "docs"
|
|
54
|
-
Requires-Dist: mkdocs-literate-nav; extra == "docs"
|
|
55
|
-
Requires-Dist: markdown-include; extra == "docs"
|
|
56
|
-
Requires-Dist: pymdown-extensions; extra == "docs"
|
|
57
|
-
Requires-Dist: pygments; extra == "docs"
|
|
58
|
-
Requires-Dist: mike; extra == "docs"
|
|
49
|
+
Requires-Dist: mkdocs-material<10,>=9.0.0; extra == "docs"
|
|
50
|
+
Requires-Dist: mkdocstrings-python>=1.0.0; extra == "docs"
|
|
51
|
+
Requires-Dist: mkdocs-table-reader-plugin>=2.0.0; extra == "docs"
|
|
52
|
+
Requires-Dist: mkdocs-gen-files>=0.4.0; extra == "docs"
|
|
53
|
+
Requires-Dist: mkdocs-include-markdown-plugin>=6.0.0; extra == "docs"
|
|
54
|
+
Requires-Dist: mkdocs-literate-nav>=0.6.0; extra == "docs"
|
|
55
|
+
Requires-Dist: markdown-include>=0.8.0; extra == "docs"
|
|
56
|
+
Requires-Dist: pymdown-extensions>=10.0.0; extra == "docs"
|
|
57
|
+
Requires-Dist: pygments>=2.14.0; extra == "docs"
|
|
58
|
+
Requires-Dist: mike<2,>=1.1.0; extra == "docs"
|
|
59
59
|
Dynamic: license-file
|
|
60
60
|
|
|
61
61
|
# FlixOpt: Energy and Material Flow Optimization Framework
|
|
@@ -31,3 +31,8 @@ if __name__ == '__main__':
|
|
|
31
31
|
# --- Plotting internal variables manually ---
|
|
32
32
|
results.plot_heatmap('BHKW2(Q_th)|on')
|
|
33
33
|
results.plot_heatmap('Kessel(Q_th)|on')
|
|
34
|
+
|
|
35
|
+
# Dataframes from results:
|
|
36
|
+
fw_bus = results['Fernwärme'].node_balance().to_dataframe()
|
|
37
|
+
all = results.solution.to_dataframe()
|
|
38
|
+
|
|
@@ -491,7 +491,7 @@ class StorageModel(ComponentModel):
|
|
|
491
491
|
self.add(
|
|
492
492
|
self._model.add_constraints(
|
|
493
493
|
charge_state.isel(time=slice(1, None))
|
|
494
|
-
== charge_state.isel(time=slice(None, -1)) * (1 - rel_loss
|
|
494
|
+
== charge_state.isel(time=slice(None, -1)) * ((1 - rel_loss) ** hours_per_step)
|
|
495
495
|
+ charge_rate * eff_charge * hours_per_step
|
|
496
496
|
- discharge_rate * eff_discharge * hours_per_step,
|
|
497
497
|
name=f'{self.label_full}|charge_state',
|
|
@@ -62,13 +62,17 @@ class DataConverter:
|
|
|
62
62
|
return xr.DataArray(data, coords=coords, dims=dims)
|
|
63
63
|
elif isinstance(data, pd.DataFrame):
|
|
64
64
|
if not data.index.equals(timesteps):
|
|
65
|
-
raise ConversionError("DataFrame index doesn't match timesteps index"
|
|
65
|
+
raise ConversionError(f"DataFrame index doesn't match timesteps index. "
|
|
66
|
+
f"Its missing the following time steps: {timesteps.difference(data.index)}. "
|
|
67
|
+
f"Some parameters might need an extra timestep at the end.")
|
|
66
68
|
if not len(data.columns) == 1:
|
|
67
69
|
raise ConversionError('DataFrame must have exactly one column')
|
|
68
70
|
return xr.DataArray(data.values.flatten(), coords=coords, dims=dims)
|
|
69
71
|
elif isinstance(data, pd.Series):
|
|
70
72
|
if not data.index.equals(timesteps):
|
|
71
|
-
raise ConversionError("Series index doesn't match timesteps index"
|
|
73
|
+
raise ConversionError(f"Series index doesn't match timesteps index. "
|
|
74
|
+
f"Its missing the following time steps: {timesteps.difference(data.index)}. "
|
|
75
|
+
f"Some parameters might need an extra timestep at the end.")
|
|
72
76
|
return xr.DataArray(data.values, coords=coords, dims=dims)
|
|
73
77
|
elif isinstance(data, np.ndarray):
|
|
74
78
|
if data.ndim != 1:
|
|
@@ -94,7 +94,7 @@ class Effect(Element):
|
|
|
94
94
|
f'{self.label_full}|minimum_operation_per_hour', self.minimum_operation_per_hour
|
|
95
95
|
)
|
|
96
96
|
self.maximum_operation_per_hour = flow_system.create_time_series(
|
|
97
|
-
f'{self.label_full}|maximum_operation_per_hour', self.maximum_operation_per_hour,
|
|
97
|
+
f'{self.label_full}|maximum_operation_per_hour', self.maximum_operation_per_hour,
|
|
98
98
|
)
|
|
99
99
|
|
|
100
100
|
self.specific_share_to_other_effects_operation = flow_system.create_effect_time_series(
|