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.

Files changed (105) hide show
  1. flixopt-2.1.3/.github/CONTRIBUTING.md +85 -0
  2. flixopt-2.1.3/.github/ISSUE_TEMPLATE/bug_report.yml +81 -0
  3. flixopt-2.1.3/.github/ISSUE_TEMPLATE/config.yml +8 -0
  4. flixopt-2.1.3/.github/ISSUE_TEMPLATE/feature_request.yml +88 -0
  5. flixopt-2.1.3/.github/pull_request_template.md +20 -0
  6. {flixopt-2.1.1 → flixopt-2.1.3}/.github/workflows/python-app.yaml +78 -7
  7. flixopt-2.1.3/CHANGELOG.md +87 -0
  8. {flixopt-2.1.1 → flixopt-2.1.3}/PKG-INFO +29 -29
  9. {flixopt-2.1.1 → flixopt-2.1.3}/docs/SUMMARY.md +1 -1
  10. {flixopt-2.1.1 → flixopt-2.1.3}/examples/02_Complex/complex_example_results.py +5 -0
  11. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/components.py +1 -1
  12. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/core.py +6 -2
  13. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/effects.py +1 -1
  14. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt.egg-info/PKG-INFO +29 -29
  15. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt.egg-info/SOURCES.txt +7 -8
  16. flixopt-2.1.3/flixopt.egg-info/requires.txt +39 -0
  17. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt.egg-info/top_level.txt +0 -1
  18. {flixopt-2.1.1 → flixopt-2.1.3}/mkdocs.yml +3 -2
  19. {flixopt-2.1.1 → flixopt-2.1.3}/pyproject.toml +40 -31
  20. flixopt-2.1.3/scripts/extract_release_notes.py +45 -0
  21. {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_storage.py +1 -1
  22. flixopt-2.1.1/.github/workflows/deploy-docs.yaml +0 -33
  23. flixopt-2.1.1/docs/release-notes/_template.txt +0 -32
  24. flixopt-2.1.1/docs/release-notes/index.md +0 -7
  25. flixopt-2.1.1/docs/release-notes/v2.0.0.md +0 -93
  26. flixopt-2.1.1/docs/release-notes/v2.0.1.md +0 -12
  27. flixopt-2.1.1/docs/release-notes/v2.1.0.md +0 -31
  28. flixopt-2.1.1/docs/release-notes/v2.1.1.md +0 -11
  29. flixopt-2.1.1/flixopt.egg-info/requires.txt +0 -37
  30. flixopt-2.1.1/site/release-notes/_template.txt +0 -32
  31. {flixopt-2.1.1 → flixopt-2.1.3}/.gitignore +0 -0
  32. {flixopt-2.1.1 → flixopt-2.1.3}/LICENSE +0 -0
  33. {flixopt-2.1.1 → flixopt-2.1.3}/README.md +0 -0
  34. {flixopt-2.1.1 → flixopt-2.1.3}/docs/contribute.md +0 -0
  35. {flixopt-2.1.1 → flixopt-2.1.3}/docs/examples/00-Minimal Example.md +0 -0
  36. {flixopt-2.1.1 → flixopt-2.1.3}/docs/examples/01-Basic Example.md +0 -0
  37. {flixopt-2.1.1 → flixopt-2.1.3}/docs/examples/02-Complex Example.md +0 -0
  38. {flixopt-2.1.1 → flixopt-2.1.3}/docs/examples/03-Calculation Modes.md +0 -0
  39. {flixopt-2.1.1 → flixopt-2.1.3}/docs/examples/index.md +0 -0
  40. {flixopt-2.1.1 → flixopt-2.1.3}/docs/faq/contribute.md +0 -0
  41. {flixopt-2.1.1 → flixopt-2.1.3}/docs/faq/index.md +0 -0
  42. {flixopt-2.1.1 → flixopt-2.1.3}/docs/getting-started.md +0 -0
  43. {flixopt-2.1.1 → flixopt-2.1.3}/docs/images/architecture_flixOpt-pre2.0.0.png +0 -0
  44. {flixopt-2.1.1 → flixopt-2.1.3}/docs/images/architecture_flixOpt.png +0 -0
  45. {flixopt-2.1.1 → flixopt-2.1.3}/docs/images/flixopt-icon.svg +0 -0
  46. {flixopt-2.1.1 → flixopt-2.1.3}/docs/index.md +0 -0
  47. {flixopt-2.1.1 → flixopt-2.1.3}/docs/javascripts/mathjax.js +0 -0
  48. {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/Mathematical Notation/Bus.md +0 -0
  49. {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/Mathematical Notation/Effects, Penalty & Objective.md +0 -0
  50. {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/Mathematical Notation/Flow.md +0 -0
  51. {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/Mathematical Notation/LinearConverter.md +0 -0
  52. {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/Mathematical Notation/Piecewise.md +0 -0
  53. {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/Mathematical Notation/Storage.md +0 -0
  54. {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/Mathematical Notation/index.md +0 -0
  55. {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/Mathematical Notation/others.md +0 -0
  56. {flixopt-2.1.1 → flixopt-2.1.3}/docs/user-guide/index.md +0 -0
  57. {flixopt-2.1.1 → flixopt-2.1.3}/examples/00_Minmal/minimal_example.py +0 -0
  58. {flixopt-2.1.1 → flixopt-2.1.3}/examples/01_Simple/simple_example.py +0 -0
  59. {flixopt-2.1.1 → flixopt-2.1.3}/examples/02_Complex/complex_example.py +0 -0
  60. {flixopt-2.1.1 → flixopt-2.1.3}/examples/03_Calculation_types/Zeitreihen2020.csv +0 -0
  61. {flixopt-2.1.1 → flixopt-2.1.3}/examples/03_Calculation_types/example_calculation_types.py +0 -0
  62. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/__init__.py +0 -0
  63. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/aggregation.py +0 -0
  64. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/calculation.py +0 -0
  65. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/commons.py +0 -0
  66. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/config.py +0 -0
  67. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/config.yaml +0 -0
  68. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/elements.py +0 -0
  69. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/features.py +0 -0
  70. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/flow_system.py +0 -0
  71. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/interface.py +0 -0
  72. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/io.py +0 -0
  73. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/linear_converters.py +0 -0
  74. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/plotting.py +0 -0
  75. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/results.py +0 -0
  76. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/solvers.py +0 -0
  77. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/structure.py +0 -0
  78. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt/utils.py +0 -0
  79. {flixopt-2.1.1 → flixopt-2.1.3}/flixopt.egg-info/dependency_links.txt +0 -0
  80. {flixopt-2.1.1 → flixopt-2.1.3}/pics/architecture_flixOpt-pre2.0.0.png +0 -0
  81. {flixopt-2.1.1 → flixopt-2.1.3}/pics/architecture_flixOpt.png +0 -0
  82. {flixopt-2.1.1 → flixopt-2.1.3}/pics/flixOpt_plotting.jpg +0 -0
  83. {flixopt-2.1.1 → flixopt-2.1.3}/pics/flixopt-icon.svg +0 -0
  84. {flixopt-2.1.1 → flixopt-2.1.3}/pics/pics.pptx +0 -0
  85. {flixopt-2.1.1 → flixopt-2.1.3}/scripts/gen_ref_pages.py +0 -0
  86. {flixopt-2.1.1 → flixopt-2.1.3}/setup.cfg +0 -0
  87. {flixopt-2.1.1 → flixopt-2.1.3}/tests/__init__.py +0 -0
  88. {flixopt-2.1.1 → flixopt-2.1.3}/tests/conftest.py +0 -0
  89. {flixopt-2.1.1 → flixopt-2.1.3}/tests/ressources/Zeitreihen2020.csv +0 -0
  90. {flixopt-2.1.1 → flixopt-2.1.3}/tests/run_all_tests.py +0 -0
  91. {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_bus.py +0 -0
  92. {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_component.py +0 -0
  93. {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_dataconverter.py +0 -0
  94. {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_effect.py +0 -0
  95. {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_examples.py +0 -0
  96. {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_flow.py +0 -0
  97. {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_functional.py +0 -0
  98. {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_integration.py +0 -0
  99. {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_io.py +0 -0
  100. {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_linear_converter.py +0 -0
  101. {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_on_hours_computation.py +0 -0
  102. {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_plots.py +0 -0
  103. {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_results_plots.py +0 -0
  104. {flixopt-2.1.1 → flixopt-2.1.3}/tests/test_timeseries.py +0 -0
  105. {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] # Only run after tests pass
63
- if: github.event_name == 'release' && github.event.action == 'created' # Only on release creation
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: [test] # Only run after TestPyPI publish succeeds
108
- if: github.event_name == 'release' && github.event.action == 'created' # Only on release creation
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.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>=1.21.5
26
- Requires-Dist: PyYAML>=6.0
27
- Requires-Dist: linopy>=0.5.1
28
- Requires-Dist: netcdf4>=1.6.1
29
- Requires-Dist: rich>=13.0.1
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: pandas<3,>=2
32
- Requires-Dist: matplotlib>=3.5.2
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>=2.3.1; extra == "dev"
40
- Requires-Dist: scipy>=1.15.1; extra == "dev"
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>=2.3.1; extra == "full"
45
- Requires-Dist: scipy>=1.15.1; extra == "full"
46
- Requires-Dist: streamlit>=1.44.0; extra == "full"
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>=9.0.0; extra == "docs"
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
@@ -4,4 +4,4 @@
4
4
  - [Examples](examples/)
5
5
  - [FAQ](faq/)
6
6
  - [API-Reference](api-reference/)
7
- - [Release Notes](release-notes/)
7
+ - [Release Notes](changelog.md)
@@ -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 * hours_per_step)
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, flow_system
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(