flixopt 3.0.1__py3-none-any.whl → 3.0.3__py3-none-any.whl

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/plotting.py CHANGED
@@ -327,7 +327,7 @@ class ColorProcessor:
327
327
 
328
328
  def with_plotly(
329
329
  data: pd.DataFrame,
330
- style: Literal['stacked_bar', 'line', 'area', 'grouped_bar'] = 'stacked_bar',
330
+ mode: Literal['stacked_bar', 'line', 'area', 'grouped_bar'] = 'stacked_bar',
331
331
  colors: ColorType = 'viridis',
332
332
  title: str = '',
333
333
  ylabel: str = '',
@@ -340,7 +340,7 @@ def with_plotly(
340
340
  Args:
341
341
  data: A DataFrame containing the data to plot, where the index represents time (e.g., hours),
342
342
  and each column represents a separate data series.
343
- style: The plotting style. Use 'stacked_bar' for stacked bar charts, 'line' for stepped lines,
343
+ mode: The plotting mode. Use 'stacked_bar' for stacked bar charts, 'line' for stepped lines,
344
344
  or 'area' for stacked area charts.
345
345
  colors: Color specification, can be:
346
346
  - A string with a colorscale name (e.g., 'viridis', 'plasma')
@@ -354,8 +354,8 @@ def with_plotly(
354
354
  Returns:
355
355
  A Plotly figure object containing the generated plot.
356
356
  """
357
- if style not in ('stacked_bar', 'line', 'area', 'grouped_bar'):
358
- raise ValueError(f"'style' must be one of {{'stacked_bar','line','area', 'grouped_bar'}}, got {style!r}")
357
+ if mode not in ('stacked_bar', 'line', 'area', 'grouped_bar'):
358
+ raise ValueError(f"'mode' must be one of {{'stacked_bar','line','area', 'grouped_bar'}}, got {mode!r}")
359
359
  if data.empty:
360
360
  return go.Figure()
361
361
 
@@ -363,7 +363,7 @@ def with_plotly(
363
363
 
364
364
  fig = fig if fig is not None else go.Figure()
365
365
 
366
- if style == 'stacked_bar':
366
+ if mode == 'stacked_bar':
367
367
  for i, column in enumerate(data.columns):
368
368
  fig.add_trace(
369
369
  go.Bar(
@@ -381,7 +381,7 @@ def with_plotly(
381
381
  bargap=0, # No space between bars
382
382
  bargroupgap=0, # No space between grouped bars
383
383
  )
384
- if style == 'grouped_bar':
384
+ if mode == 'grouped_bar':
385
385
  for i, column in enumerate(data.columns):
386
386
  fig.add_trace(go.Bar(x=data.index, y=data[column], name=column, marker=dict(color=processed_colors[i])))
387
387
 
@@ -390,7 +390,7 @@ def with_plotly(
390
390
  bargap=0.2, # No space between bars
391
391
  bargroupgap=0, # space between grouped bars
392
392
  )
393
- elif style == 'line':
393
+ elif mode == 'line':
394
394
  for i, column in enumerate(data.columns):
395
395
  fig.add_trace(
396
396
  go.Scatter(
@@ -401,7 +401,7 @@ def with_plotly(
401
401
  line=dict(shape='hv', color=processed_colors[i]),
402
402
  )
403
403
  )
404
- elif style == 'area':
404
+ elif mode == 'area':
405
405
  data = data.copy()
406
406
  data[(data > -1e-5) & (data < 1e-5)] = 0 # Preventing issues with plotting
407
407
  # Split columns into positive, negative, and mixed categories
@@ -468,7 +468,7 @@ def with_plotly(
468
468
 
469
469
  def with_matplotlib(
470
470
  data: pd.DataFrame,
471
- style: Literal['stacked_bar', 'line'] = 'stacked_bar',
471
+ mode: Literal['stacked_bar', 'line'] = 'stacked_bar',
472
472
  colors: ColorType = 'viridis',
473
473
  title: str = '',
474
474
  ylabel: str = '',
@@ -483,7 +483,7 @@ def with_matplotlib(
483
483
  Args:
484
484
  data: A DataFrame containing the data to plot. The index should represent time (e.g., hours),
485
485
  and each column represents a separate data series.
486
- style: Plotting style. Use 'stacked_bar' for stacked bar charts or 'line' for stepped lines.
486
+ mode: Plotting mode. Use 'stacked_bar' for stacked bar charts or 'line' for stepped lines.
487
487
  colors: Color specification, can be:
488
488
  - A string with a colormap name (e.g., 'viridis', 'plasma')
489
489
  - A list of color strings (e.g., ['#ff0000', '#00ff00'])
@@ -499,19 +499,19 @@ def with_matplotlib(
499
499
  A tuple containing the Matplotlib figure and axes objects used for the plot.
500
500
 
501
501
  Notes:
502
- - If `style` is 'stacked_bar', bars are stacked for both positive and negative values.
502
+ - If `mode` is 'stacked_bar', bars are stacked for both positive and negative values.
503
503
  Negative values are stacked separately without extra labels in the legend.
504
- - If `style` is 'line', stepped lines are drawn for each data series.
504
+ - If `mode` is 'line', stepped lines are drawn for each data series.
505
505
  """
506
- if style not in ('stacked_bar', 'line'):
507
- raise ValueError(f"'style' must be one of {{'stacked_bar','line'}} for matplotlib, got {style!r}")
506
+ if mode not in ('stacked_bar', 'line'):
507
+ raise ValueError(f"'mode' must be one of {{'stacked_bar','line'}} for matplotlib, got {mode!r}")
508
508
 
509
509
  if fig is None or ax is None:
510
510
  fig, ax = plt.subplots(figsize=figsize)
511
511
 
512
512
  processed_colors = ColorProcessor(engine='matplotlib').process_colors(colors, list(data.columns))
513
513
 
514
- if style == 'stacked_bar':
514
+ if mode == 'stacked_bar':
515
515
  cumulative_positive = np.zeros(len(data))
516
516
  cumulative_negative = np.zeros(len(data))
517
517
  width = data.index.to_series().diff().dropna().min() # Minimum time difference
@@ -542,7 +542,7 @@ def with_matplotlib(
542
542
  )
543
543
  cumulative_negative += negative_values.values
544
544
 
545
- elif style == 'line':
545
+ elif mode == 'line':
546
546
  for i, column in enumerate(data.columns):
547
547
  ax.step(data.index, data[column], where='post', color=processed_colors[i], label=column)
548
548
 
flixopt/results.py CHANGED
@@ -921,8 +921,8 @@ class _NodeResults(_ElementResults):
921
921
  colors: plotting.ColorType = 'viridis',
922
922
  engine: plotting.PlottingEngine = 'plotly',
923
923
  indexer: dict[FlowSystemDimensions, Any] | None = None,
924
- mode: Literal['flow_rate', 'flow_hours'] = 'flow_rate',
925
- style: Literal['area', 'stacked_bar', 'line'] = 'stacked_bar',
924
+ unit_type: Literal['flow_rate', 'flow_hours'] = 'flow_rate',
925
+ mode: Literal['area', 'stacked_bar', 'line'] = 'stacked_bar',
926
926
  drop_suffix: bool = True,
927
927
  ) -> plotly.graph_objs.Figure | tuple[plt.Figure, plt.Axes]:
928
928
  """
@@ -935,23 +935,26 @@ class _NodeResults(_ElementResults):
935
935
  indexer: Optional selection dict, e.g., {'scenario': 'base', 'period': 2024}.
936
936
  If None, uses first value for each dimension (except time).
937
937
  If empty dict {}, uses all values.
938
- style: The style to use for the dataset. Can be 'flow_rate' or 'flow_hours'.
938
+ unit_type: The unit type to use for the dataset. Can be 'flow_rate' or 'flow_hours'.
939
939
  - 'flow_rate': Returns the flow_rates of the Node.
940
940
  - 'flow_hours': Returns the flow_hours of the Node. [flow_hours(t) = flow_rate(t) * dt(t)]. Renames suffixes to |flow_hours.
941
+ mode: The plotting mode. Use 'stacked_bar' for stacked bar charts, 'line' for stepped lines, or 'area' for stacked area charts.
941
942
  drop_suffix: Whether to drop the suffix from the variable names.
942
943
  """
943
- ds = self.node_balance(with_last_timestep=True, mode=mode, drop_suffix=drop_suffix, indexer=indexer)
944
+ ds = self.node_balance(with_last_timestep=True, unit_type=unit_type, drop_suffix=drop_suffix, indexer=indexer)
944
945
 
945
946
  ds, suffix_parts = _apply_indexer_to_data(ds, indexer, drop=True)
946
947
  suffix = '--' + '-'.join(suffix_parts) if suffix_parts else ''
947
948
 
948
- title = f'{self.label} (flow rates){suffix}' if mode == 'flow_rate' else f'{self.label} (flow hours){suffix}'
949
+ title = (
950
+ f'{self.label} (flow rates){suffix}' if unit_type == 'flow_rate' else f'{self.label} (flow hours){suffix}'
951
+ )
949
952
 
950
953
  if engine == 'plotly':
951
954
  figure_like = plotting.with_plotly(
952
955
  ds.to_dataframe(),
953
956
  colors=colors,
954
- style=style,
957
+ mode=mode,
955
958
  title=title,
956
959
  )
957
960
  default_filetype = '.html'
@@ -959,7 +962,7 @@ class _NodeResults(_ElementResults):
959
962
  figure_like = plotting.with_matplotlib(
960
963
  ds.to_dataframe(),
961
964
  colors=colors,
962
- style=style,
965
+ mode=mode,
963
966
  title=title,
964
967
  )
965
968
  default_filetype = '.png'
@@ -1063,7 +1066,7 @@ class _NodeResults(_ElementResults):
1063
1066
  negate_outputs: bool = False,
1064
1067
  threshold: float | None = 1e-5,
1065
1068
  with_last_timestep: bool = False,
1066
- mode: Literal['flow_rate', 'flow_hours'] = 'flow_rate',
1069
+ unit_type: Literal['flow_rate', 'flow_hours'] = 'flow_rate',
1067
1070
  drop_suffix: bool = False,
1068
1071
  indexer: dict[FlowSystemDimensions, Any] | None = None,
1069
1072
  ) -> xr.Dataset:
@@ -1074,7 +1077,7 @@ class _NodeResults(_ElementResults):
1074
1077
  negate_outputs: Whether to negate the output flow_rates of the Node.
1075
1078
  threshold: The threshold for small values. Variables with all values below the threshold are dropped.
1076
1079
  with_last_timestep: Whether to include the last timestep in the dataset.
1077
- mode: The mode to use for the dataset. Can be 'flow_rate' or 'flow_hours'.
1080
+ unit_type: The unit type to use for the dataset. Can be 'flow_rate' or 'flow_hours'.
1078
1081
  - 'flow_rate': Returns the flow_rates of the Node.
1079
1082
  - 'flow_hours': Returns the flow_hours of the Node. [flow_hours(t) = flow_rate(t) * dt(t)]. Renames suffixes to |flow_hours.
1080
1083
  drop_suffix: Whether to drop the suffix from the variable names.
@@ -1102,7 +1105,7 @@ class _NodeResults(_ElementResults):
1102
1105
 
1103
1106
  ds, _ = _apply_indexer_to_data(ds, indexer, drop=True)
1104
1107
 
1105
- if mode == 'flow_hours':
1108
+ if unit_type == 'flow_hours':
1106
1109
  ds = ds * self._calculation_results.hours_per_timestep
1107
1110
  ds = ds.rename_vars({var: var.replace('flow_rate', 'flow_hours') for var in ds.data_vars})
1108
1111
 
@@ -1137,7 +1140,7 @@ class ComponentResults(_NodeResults):
1137
1140
  show: bool = True,
1138
1141
  colors: plotting.ColorType = 'viridis',
1139
1142
  engine: plotting.PlottingEngine = 'plotly',
1140
- style: Literal['area', 'stacked_bar', 'line'] = 'stacked_bar',
1143
+ mode: Literal['area', 'stacked_bar', 'line'] = 'stacked_bar',
1141
1144
  indexer: dict[FlowSystemDimensions, Any] | None = None,
1142
1145
  ) -> plotly.graph_objs.Figure:
1143
1146
  """Plot storage charge state over time, combined with the node balance.
@@ -1147,7 +1150,7 @@ class ComponentResults(_NodeResults):
1147
1150
  show: Whether to show the plot or not.
1148
1151
  colors: Color scheme. Also see plotly.
1149
1152
  engine: Plotting engine to use. Only 'plotly' is implemented atm.
1150
- style: The colors to use for the plot. See `flixopt.plotting.ColorType` for options.
1153
+ mode: The plotting mode. Use 'stacked_bar' for stacked bar charts, 'line' for stepped lines, or 'area' for stacked area charts.
1151
1154
  indexer: Optional selection dict, e.g., {'scenario': 'base', 'period': 2024}.
1152
1155
  If None, uses first value for each dimension.
1153
1156
  If empty dict {}, uses all values.
@@ -1171,7 +1174,7 @@ class ComponentResults(_NodeResults):
1171
1174
  fig = plotting.with_plotly(
1172
1175
  ds.to_dataframe(),
1173
1176
  colors=colors,
1174
- style=style,
1177
+ mode=mode,
1175
1178
  title=title,
1176
1179
  )
1177
1180
 
@@ -1187,7 +1190,7 @@ class ComponentResults(_NodeResults):
1187
1190
  fig, ax = plotting.with_matplotlib(
1188
1191
  ds.to_dataframe(),
1189
1192
  colors=colors,
1190
- style=style,
1193
+ mode=mode,
1191
1194
  title=title,
1192
1195
  )
1193
1196
 
@@ -0,0 +1,272 @@
1
+ Metadata-Version: 2.4
2
+ Name: flixopt
3
+ Version: 3.0.3
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-Expression: MIT
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
+ Project-URL: documentation, https://flixopt.github.io/flixopt/
11
+ Keywords: optimization,energy systems,numerical analysis
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: Intended Audience :: Science/Research
19
+ Classifier: Topic :: Scientific/Engineering
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: numpy<3,>=1.21.5
24
+ Requires-Dist: pandas<3,>=2.0.0
25
+ Requires-Dist: xarray<2026.0,>=2024.2.0
26
+ Requires-Dist: linopy<0.6,>=0.5.1
27
+ Requires-Dist: h5netcdf<2,>=1.0.0
28
+ Requires-Dist: pyyaml<7,>=6.0.0
29
+ Requires-Dist: rich<15,>=13.0.0
30
+ Requires-Dist: tomli<3,>=2.0.1; python_version < "3.11"
31
+ Requires-Dist: highspy<2,>=1.5.3
32
+ Requires-Dist: matplotlib<4,>=3.5.2
33
+ Requires-Dist: plotly<7,>=5.15.0
34
+ Requires-Dist: numexpr<2.14,>=2.8.4; python_version < "3.11"
35
+ Provides-Extra: network-viz
36
+ Requires-Dist: dash<4,>=3.0.0; extra == "network-viz"
37
+ Requires-Dist: dash-cytoscape<2,>=1.0.0; extra == "network-viz"
38
+ Requires-Dist: dash-daq<1,>=0.6.0; extra == "network-viz"
39
+ Requires-Dist: networkx<4,>=3.0.0; extra == "network-viz"
40
+ Requires-Dist: werkzeug<4,>=3.0.0; extra == "network-viz"
41
+ Requires-Dist: flask<4,>=3.0.0; extra == "network-viz"
42
+ Provides-Extra: full
43
+ Requires-Dist: pyvis==0.3.2; extra == "full"
44
+ Requires-Dist: tsam<3,>=2.3.1; extra == "full"
45
+ Requires-Dist: scipy<2,>=1.15.1; extra == "full"
46
+ Requires-Dist: gurobipy<13,>=10.0.0; extra == "full"
47
+ Requires-Dist: dash<4,>=3.0.0; extra == "full"
48
+ Requires-Dist: dash-cytoscape<2,>=1.0.0; extra == "full"
49
+ Requires-Dist: dash-daq<1,>=0.6.0; extra == "full"
50
+ Requires-Dist: networkx<4,>=3.0.0; extra == "full"
51
+ Requires-Dist: werkzeug<4,>=3.0.0; extra == "full"
52
+ Requires-Dist: flask<4,>=3.0.0; extra == "full"
53
+ Provides-Extra: dev
54
+ Requires-Dist: pytest==8.4.2; extra == "dev"
55
+ Requires-Dist: pytest-xdist==3.8.0; extra == "dev"
56
+ Requires-Dist: nbformat==5.10.4; extra == "dev"
57
+ Requires-Dist: ruff==0.13.3; extra == "dev"
58
+ Requires-Dist: pre-commit==4.3.0; extra == "dev"
59
+ Requires-Dist: pyvis==0.3.2; extra == "dev"
60
+ Requires-Dist: tsam==2.3.9; extra == "dev"
61
+ Requires-Dist: scipy==1.15.1; extra == "dev"
62
+ Requires-Dist: gurobipy==12.0.3; extra == "dev"
63
+ Requires-Dist: dash==3.0.0; extra == "dev"
64
+ Requires-Dist: dash-cytoscape==1.0.2; extra == "dev"
65
+ Requires-Dist: dash-daq==0.6.0; extra == "dev"
66
+ Requires-Dist: networkx==3.0.0; extra == "dev"
67
+ Requires-Dist: werkzeug==3.0.0; extra == "dev"
68
+ Provides-Extra: docs
69
+ Requires-Dist: mkdocs-material==9.6.21; extra == "docs"
70
+ Requires-Dist: mkdocstrings-python==1.18.2; extra == "docs"
71
+ Requires-Dist: mkdocs-table-reader-plugin==3.1.0; extra == "docs"
72
+ Requires-Dist: mkdocs-gen-files==0.5.0; extra == "docs"
73
+ Requires-Dist: mkdocs-include-markdown-plugin==7.1.7; extra == "docs"
74
+ Requires-Dist: mkdocs-literate-nav==0.6.2; extra == "docs"
75
+ Requires-Dist: markdown-include==0.8.1; extra == "docs"
76
+ Requires-Dist: pymdown-extensions==10.16.1; extra == "docs"
77
+ Requires-Dist: pygments==2.19.2; extra == "docs"
78
+ Requires-Dist: mike==2.1.3; extra == "docs"
79
+ Dynamic: license-file
80
+
81
+ # FlixOpt: Energy and Material Flow Optimization Framework
82
+
83
+ [![Documentation](https://img.shields.io/badge/docs-latest-brightgreen.svg)](https://flixopt.github.io/flixopt/latest/)
84
+ [![Build Status](https://github.com/flixOpt/flixopt/actions/workflows/python-app.yaml/badge.svg)](https://github.com/flixOpt/flixopt/actions/workflows/python-app.yaml)
85
+ [![PyPI version](https://img.shields.io/pypi/v/flixopt)](https://pypi.org/project/flixopt/)
86
+ [![PyPI status](https://img.shields.io/pypi/status/flixopt.svg)](https://pypi.org/project/flixopt/)
87
+ [![Python Versions](https://img.shields.io/pypi/pyversions/flixopt.svg)](https://pypi.org/project/flixopt/)
88
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
89
+ [![PyPI downloads](https://img.shields.io/pypi/dm/flixopt)](https://pypi.org/project/flixopt/)
90
+ [![GitHub last commit](https://img.shields.io/github/last-commit/flixOpt/flixopt)](https://github.com/flixOpt/flixopt/commits/main)
91
+ [![GitHub issues](https://img.shields.io/github/issues/flixOpt/flixopt)](https://github.com/flixOpt/flixopt/issues)
92
+ [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/flixOpt/flixopt/main.svg)](https://results.pre-commit.ci/latest/github/flixOpt/flixopt/main)
93
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
94
+ [![Powered by linopy](https://img.shields.io/badge/powered%20by-linopy-blue)](https://github.com/PyPSA/linopy/)
95
+ [![Powered by xarray](https://img.shields.io/badge/powered%20by-xarray-blue)](https://xarray.dev/)
96
+ [![DOI](https://img.shields.io/badge/DOI-10.18086%2Feurosun.2022.04.07-blue)](https://doi.org/10.18086/eurosun.2022.04.07)
97
+ [![GitHub stars](https://img.shields.io/github/stars/flixOpt/flixopt?style=social)](https://github.com/flixOpt/flixopt/stargazers)
98
+
99
+ ---
100
+
101
+ **FlixOpt is a Python framework for optimizing energy and material flow systems** - from district heating networks to industrial production lines, from renewable energy portfolios to supply chain logistics.
102
+
103
+ **Start simple, scale complex:** Build a working optimization model in minutes, then progressively add detail - multi-period investments, stochastic scenarios, custom constraints - without rewriting your code.
104
+
105
+ ---
106
+
107
+ ## 🚀 Quick Start
108
+
109
+ ```bash
110
+ pip install flixopt
111
+ ```
112
+
113
+ That's it! FlixOpt comes with the [HiGHS](https://highs.dev/) solver included. You're ready to optimize.
114
+
115
+ **The basic workflow:**
116
+
117
+ ```python
118
+ import flixopt as fx
119
+
120
+ # 1. Define your system structure
121
+ flow_system = fx.FlowSystem(timesteps)
122
+ flow_system.add_elements(buses, components, effects)
123
+
124
+ # 2. Create and solve
125
+ calculation = fx.FullCalculation("MyModel", flow_system)
126
+ calculation.solve()
127
+
128
+ # 3. Analyze results
129
+ calculation.results.solution
130
+ ```
131
+
132
+ **Get started with real examples:**
133
+ - 📚 [Full Documentation](https://flixopt.github.io/flixopt/latest/)
134
+ - 💡 [Examples Gallery](https://flixopt.github.io/flixopt/latest/examples/) - Complete working examples from simple to complex
135
+ - 🔧 [API Reference](https://flixopt.github.io/flixopt/latest/api-reference/)
136
+
137
+ ---
138
+
139
+ ## 🌟 Why FlixOpt?
140
+
141
+ ### Progressive Enhancement - Your Model Grows With You
142
+
143
+ **Start simple:**
144
+ ```python
145
+ # Basic single-period model
146
+ flow_system = fx.FlowSystem(timesteps)
147
+ boiler = fx.Boiler("Boiler", eta=0.9, ...)
148
+ ```
149
+
150
+ **Add complexity incrementally:**
151
+ - **Investment decisions** → Add `InvestParameters` to components
152
+ - **Multi-period planning** → Add `periods` dimension to FlowSystem
153
+ - **Uncertainty modeling** → Add `scenarios` dimension with probabilities
154
+ - **Custom constraints** → Extend with native linopy syntax
155
+
156
+ **No refactoring required.** Your component definitions stay the same - periods, scenarios, and features are added as dimensions and parameters.
157
+
158
+ → [Learn more about multi-period and stochastic modeling](https://flixopt.github.io/flixopt/latest/user-guide/mathematical-notation/dimensions/)
159
+
160
+ ### For Everyone
161
+
162
+ - **Beginners:** High-level components that "just work"
163
+ - **Experts:** Full access to modify models with linopy
164
+ - **Researchers:** Quick prototyping with customization options
165
+ - **Engineers:** Reliable, tested components without black boxes
166
+ - **Students:** Clear, Pythonic interfaces for learning optimization
167
+
168
+ ### Key Features
169
+
170
+ **Multi-criteria optimization:** Model costs, emissions, resource use - any custom metric. Optimize single objectives or use weighted combinations and ε-constraints.
171
+ → [Effects documentation](https://flixopt.github.io/flixopt/latest/user-guide/mathematical-notation/effects-penalty-objective/)
172
+
173
+ **Performance at any scale:** Choose calculation modes without changing your model - Full, Segmented, or Aggregated (using [TSAM](https://github.com/FZJ-IEK3-VSA/tsam)).
174
+ → [Calculation modes](https://flixopt.github.io/flixopt/latest/api-reference/calculation/)
175
+
176
+ **Built for reproducibility:** Self-contained NetCDF result files with complete model information. Load results months later - everything is preserved.
177
+ → [Results documentation](https://flixopt.github.io/flixopt/latest/api-reference/results/)
178
+
179
+ **Flexible data operations:** Transform FlowSystems with xarray-style operations (`sel()`, `resample()`) for multi-stage optimization.
180
+
181
+ ---
182
+
183
+ ## 🎯 What is FlixOpt?
184
+
185
+ ### A General-Purpose Flow Optimization Framework
186
+
187
+ FlixOpt models **any system involving flows and conversions:**
188
+
189
+ - **Energy systems:** District heating/cooling, microgrids, renewable portfolios, sector coupling
190
+ - **Material flows:** Supply chains, production lines, chemical processes
191
+ - **Integrated systems:** Water-energy nexus, industrial symbiosis
192
+
193
+ While energy systems are our primary focus, the same foundation applies universally. This enables coupling different system types within integrated models.
194
+
195
+ ### Modern Foundations
196
+
197
+ Built on [linopy](https://github.com/PyPSA/linopy/) and [xarray](https://github.com/pydata/xarray), FlixOpt delivers **performance** and **transparency**. Full access to variables, constraints, and model structure. Extend anything with native linopy syntax.
198
+
199
+ ### Our Position
200
+
201
+ We bridge the gap between high-level strategic models (like [FINE](https://github.com/FZJ-IEK3-VSA/FINE)) and low-level dispatch tools - similar to [PyPSA](https://docs.pypsa.org/latest/). FlixOpt is the sweet spot for detailed operational planning and long-term investment analysis in the **same framework**.
202
+
203
+ ### Academic Roots
204
+
205
+ Originally developed at [TU Dresden](https://github.com/gewv-tu-dresden) for the SMARTBIOGRID project (funded by the German Federal Ministry for Economic Affairs and Energy, FKZ: 03KB159B). FlixOpt evolved from the MATLAB-based flixOptMat framework while incorporating best practices from [oemof/solph](https://github.com/oemof/oemof-solph).
206
+
207
+ ---
208
+
209
+ ## 🛣️ Roadmap
210
+
211
+ **FlixOpt aims to be the most accessible, flexible, and universal Python framework for energy and material flow optimization.** We believe optimization modeling should be approachable for beginners yet powerful for experts, minimizing context switching between different planning horizons.
212
+
213
+ **Current focus:**
214
+ - Enhanced component library (sector coupling, hydrogen, thermal networks)
215
+ - Examples showcasing multi-period and stochastic modeling
216
+ - Advanced result analysis and visualization
217
+
218
+ **Future vision:**
219
+ - Modeling to generate alternatives (MGA) for robust decision-making
220
+ - Advanced stochastic optimization (two-stage, CVaR)
221
+ - Community ecosystem of user-contributed components
222
+
223
+ → [Full roadmap and vision](https://flixopt.github.io/flixopt/latest/roadmap/)
224
+
225
+ ---
226
+
227
+ ## 🛠️ Installation
228
+
229
+ ### Basic Installation
230
+
231
+ ```bash
232
+ pip install flixopt
233
+ ```
234
+
235
+ Includes the [HiGHS](https://highs.dev/) solver - you're ready to optimize immediately.
236
+
237
+ ### Full Installation
238
+
239
+ For additional features (interactive network visualization, time series aggregation):
240
+
241
+ ```bash
242
+ pip install "flixopt[full]"
243
+ ```
244
+
245
+ ### Solver Support
246
+
247
+ FlixOpt supports many solvers via linopy: **HiGHS** (included), **Gurobi**, **CPLEX**, **CBC**, **GLPK**, and more.
248
+
249
+ → [Installation guide](https://flixopt.github.io/flixopt/latest/getting-started/)
250
+
251
+ ---
252
+
253
+ ## 🤝 Contributing
254
+
255
+ FlixOpt thrives on community input. Whether you're fixing bugs, adding components, improving docs, or sharing use cases - **we welcome your contributions.**
256
+
257
+ → [Contribution guide](https://flixopt.github.io/flixopt/latest/contribute/)
258
+
259
+ ---
260
+
261
+ ## 📖 Citation
262
+
263
+ If FlixOpt supports your research or project, please cite:
264
+
265
+ - **Main Citation:** [DOI:10.18086/eurosun.2022.04.07](https://doi.org/10.18086/eurosun.2022.04.07)
266
+ - **Short Overview:** [DOI:10.13140/RG.2.2.14948.24969](https://doi.org/10.13140/RG.2.2.14948.24969)
267
+
268
+ ---
269
+
270
+ ## 📄 License
271
+
272
+ MIT License - See [LICENSE](https://github.com/flixopt/flixopt/blob/main/LICENSE) for details.
@@ -14,13 +14,13 @@ flixopt/io.py,sha256=2ZnpoU4gVnKfv-FiwoYEA11wlqbdUU8PXJiofRSKl5M,11795
14
14
  flixopt/linear_converters.py,sha256=tcz5c1SI36hRFbCX-4NXced12ss9VETg5BE7zOdyeo4,22699
15
15
  flixopt/modeling.py,sha256=s0zipbblq-LJrSe7angKT3Imxgr3kIbprG98HUvmkzI,31322
16
16
  flixopt/network_app.py,sha256=LnVAlAgzL1BgMYLsJ20a62j6nQUmNccF1zo4ACUXzL4,29433
17
- flixopt/plotting.py,sha256=lHeSwfSaQCGP2w54S8CzSa7sWwCxMcWci1EU1TYqLWM,60909
18
- flixopt/results.py,sha256=rgyYJTcgF1DOxYSvKM__BTfVU13o13DwSBjvA4o4gdM,77773
17
+ flixopt/plotting.py,sha256=T_fUwfR6x_rEQeE2dmGE7Nvy0K7ujoLnq09NEr6Ru1I,60889
18
+ flixopt/results.py,sha256=fHcgS5b31lMJxF48-ngDTnCdCVolRKRtDQXjaZABsrA,78018
19
19
  flixopt/solvers.py,sha256=m38Smc22MJfHYMiqfNf1MA3OmvbTRm5OWS9nECkDdQk,2355
20
20
  flixopt/structure.py,sha256=ntLoj--zTnaZwNYKw-WkJTNxY0ef4zDp4S0iiSxyyxE,47707
21
21
  flixopt/utils.py,sha256=CtCMBjvq31upz7i-_1nbPnSe-1CoRoOWlPkucwiSo5Q,2930
22
- flixopt-3.0.1.dist-info/licenses/LICENSE,sha256=HKsZnbrM_3Rvnr_u9cWSG90cBsj5_slaqI_z_qcxnGI,1118
23
- flixopt-3.0.1.dist-info/METADATA,sha256=TJLBIM5v232UVDWCn5Mrq0-HAfjTW0OBUNC8KbQQIPY,10776
24
- flixopt-3.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
- flixopt-3.0.1.dist-info/top_level.txt,sha256=fanTzb9NylIXfv6Ic7spU97fVmRgGDPKvI_91tw4S3E,8
26
- flixopt-3.0.1.dist-info/RECORD,,
22
+ flixopt-3.0.3.dist-info/licenses/LICENSE,sha256=HKsZnbrM_3Rvnr_u9cWSG90cBsj5_slaqI_z_qcxnGI,1118
23
+ flixopt-3.0.3.dist-info/METADATA,sha256=d016PxDA7cMrKArNB761-4E-wUMzIcdf1HTjgYZG_BU,12669
24
+ flixopt-3.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
+ flixopt-3.0.3.dist-info/top_level.txt,sha256=fanTzb9NylIXfv6Ic7spU97fVmRgGDPKvI_91tw4S3E,8
26
+ flixopt-3.0.3.dist-info/RECORD,,
@@ -1,209 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: flixopt
3
- Version: 3.0.1
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-Expression: MIT
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
- Project-URL: documentation, https://flixopt.github.io/flixopt/
11
- Keywords: optimization,energy systems,numerical analysis
12
- Classifier: Development Status :: 3 - Alpha
13
- Classifier: Programming Language :: Python :: 3.10
14
- Classifier: Programming Language :: Python :: 3.11
15
- Classifier: Programming Language :: Python :: 3.12
16
- Classifier: Programming Language :: Python :: 3.13
17
- Classifier: Intended Audience :: Developers
18
- Classifier: Intended Audience :: Science/Research
19
- Classifier: Topic :: Scientific/Engineering
20
- Requires-Python: >=3.10
21
- Description-Content-Type: text/markdown
22
- License-File: LICENSE
23
- Requires-Dist: numpy<3,>=1.21.5
24
- Requires-Dist: pandas<3,>=2.0.0
25
- Requires-Dist: xarray<2026.0,>=2024.2.0
26
- Requires-Dist: linopy<0.6,>=0.5.1
27
- Requires-Dist: h5netcdf<2,>=1.0.0
28
- Requires-Dist: pyyaml<7,>=6.0.0
29
- Requires-Dist: rich<15,>=13.0.0
30
- Requires-Dist: tomli<3,>=2.0.1; python_version < "3.11"
31
- Requires-Dist: highspy<2,>=1.5.3
32
- Requires-Dist: matplotlib<4,>=3.5.2
33
- Requires-Dist: plotly<7,>=5.15.0
34
- Requires-Dist: numexpr<2.14,>=2.8.4; python_version < "3.11"
35
- Provides-Extra: network-viz
36
- Requires-Dist: dash<4,>=3.0.0; extra == "network-viz"
37
- Requires-Dist: dash-cytoscape<2,>=1.0.0; extra == "network-viz"
38
- Requires-Dist: dash-daq<1,>=0.6.0; extra == "network-viz"
39
- Requires-Dist: networkx<4,>=3.0.0; extra == "network-viz"
40
- Requires-Dist: werkzeug<4,>=3.0.0; extra == "network-viz"
41
- Requires-Dist: flask<4,>=3.0.0; extra == "network-viz"
42
- Provides-Extra: full
43
- Requires-Dist: pyvis==0.3.2; extra == "full"
44
- Requires-Dist: tsam<3,>=2.3.1; extra == "full"
45
- Requires-Dist: scipy<2,>=1.15.1; extra == "full"
46
- Requires-Dist: gurobipy<13,>=10.0.0; extra == "full"
47
- Requires-Dist: dash<4,>=3.0.0; extra == "full"
48
- Requires-Dist: dash-cytoscape<2,>=1.0.0; extra == "full"
49
- Requires-Dist: dash-daq<1,>=0.6.0; extra == "full"
50
- Requires-Dist: networkx<4,>=3.0.0; extra == "full"
51
- Requires-Dist: werkzeug<4,>=3.0.0; extra == "full"
52
- Requires-Dist: flask<4,>=3.0.0; extra == "full"
53
- Provides-Extra: dev
54
- Requires-Dist: pytest==8.4.2; extra == "dev"
55
- Requires-Dist: pytest-xdist==3.8.0; extra == "dev"
56
- Requires-Dist: nbformat==5.10.4; extra == "dev"
57
- Requires-Dist: ruff==0.13.3; extra == "dev"
58
- Requires-Dist: pre-commit==4.3.0; extra == "dev"
59
- Requires-Dist: pyvis==0.3.2; extra == "dev"
60
- Requires-Dist: tsam==2.3.9; extra == "dev"
61
- Requires-Dist: scipy==1.15.1; extra == "dev"
62
- Requires-Dist: gurobipy==12.0.3; extra == "dev"
63
- Requires-Dist: dash==3.0.0; extra == "dev"
64
- Requires-Dist: dash-cytoscape==1.0.2; extra == "dev"
65
- Requires-Dist: dash-daq==0.6.0; extra == "dev"
66
- Requires-Dist: networkx==3.0.0; extra == "dev"
67
- Requires-Dist: werkzeug==3.0.0; extra == "dev"
68
- Provides-Extra: docs
69
- Requires-Dist: mkdocs-material==9.6.21; extra == "docs"
70
- Requires-Dist: mkdocstrings-python==1.18.2; extra == "docs"
71
- Requires-Dist: mkdocs-table-reader-plugin==3.1.0; extra == "docs"
72
- Requires-Dist: mkdocs-gen-files==0.5.0; extra == "docs"
73
- Requires-Dist: mkdocs-include-markdown-plugin==7.1.7; extra == "docs"
74
- Requires-Dist: mkdocs-literate-nav==0.6.2; extra == "docs"
75
- Requires-Dist: markdown-include==0.8.1; extra == "docs"
76
- Requires-Dist: pymdown-extensions==10.16.1; extra == "docs"
77
- Requires-Dist: pygments==2.19.2; extra == "docs"
78
- Requires-Dist: mike==2.1.3; extra == "docs"
79
- Dynamic: license-file
80
-
81
- # FlixOpt: Energy and Material Flow Optimization Framework
82
-
83
- [![Documentation](https://img.shields.io/badge/docs-latest-brightgreen.svg)](https://flixopt.github.io/flixopt/latest/)
84
- [![Build Status](https://github.com/flixOpt/flixopt/actions/workflows/python-app.yaml/badge.svg)](https://github.com/flixOpt/flixopt/actions/workflows/python-app.yaml)
85
- [![PyPI version](https://img.shields.io/pypi/v/flixopt)](https://pypi.org/project/flixopt/)
86
- [![Python Versions](https://img.shields.io/pypi/pyversions/flixopt.svg)](https://pypi.org/project/flixopt/)
87
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
88
-
89
- ---
90
-
91
- ## 🎯 Vision
92
-
93
- **FlixOpt aims to be the most accessible and flexible Python framework for energy and material flow optimization.**
94
-
95
- We believe that optimization modeling should be **approachable for beginners** yet **powerful for experts**. Too often, frameworks force you to choose between ease of use and flexibility. FlixOpt refuses this compromise.
96
-
97
- ### Where We're Going
98
-
99
- **Short-term goals:**
100
- - **Multi-dimensional modeling**: Full support for multi-period investments and scenario-based stochastic optimization (periods and scenarios are in active development)
101
- - **Enhanced component library**: More pre-built, domain-specific components (sector coupling, hydrogen systems, thermal networks, demand-side management)
102
-
103
- **Medium-term vision:**
104
- - **Modeling to generate alternatives (MGA)**: Built-in support for exploring near-optimal solution spaces to produce more robust, diverse solutions under uncertainty
105
- - **Interactive tutorials**: Browser-based, reactive tutorials for learning FlixOpt without local installation
106
- - **Standardized cost calculations**: Align with industry standards (VDI 2067) for CAPEX/OPEX calculations
107
- - **Advanced result analysis**: Time-series aggregation, automated reporting, and rich visualization options
108
-
109
- **Long-term vision:**
110
- - **Showcase universal applicability**: FlixOpt already handles any flow-based system (supply chains, water networks, production planning, chemical processes) - we need more examples and domain-specific component libraries to demonstrate this
111
- - **Seamless integration**: First-class support for coupling with simulation tools, databases, existing energy system models, and GIS data
112
- - **Robust optimization**: Built-in uncertainty quantification and stochastic programming capabilities
113
- - **Community ecosystem**: Rich library of user-contributed components, examples, and domain-specific extensions
114
- - **Model validation tools**: Automated checks for physical plausibility, data consistency, and common modeling errors
115
-
116
- ### Why FlixOpt Exists
117
-
118
- FlixOpt is a **general-purpose framework for modeling any system involving flows and conversions** - energy, materials, fluids, goods, or data. While energy systems are our primary focus, the same mathematical foundation applies to supply chains, water networks, production lines, and more.
119
-
120
- We bridge the gap between high-level strategic models (like [FINE](https://github.com/FZJ-IEK3-VSA/FINE)) for long-term planning and low-level dispatch tools for operations. FlixOpt is the **sweet spot** for:
121
-
122
- - **Researchers** who need to prototype quickly but may require deep customization later
123
- - **Engineers** who want reliable, tested components without black-box abstractions
124
- - **Students** learning optimization who benefit from clear, Pythonic interfaces
125
- - **Practitioners** who need to move from model to production-ready results
126
- - **Domain experts** from any field where things flow, transform, and need optimizing
127
-
128
- Built on modern foundations ([linopy](https://github.com/PyPSA/linopy/) and [xarray](https://github.com/pydata/xarray)), FlixOpt delivers both **performance** and **transparency**. You can inspect everything, extend anything, and trust that your model does exactly what you designed.
129
-
130
- Originally developed at [TU Dresden](https://github.com/gewv-tu-dresden) for the SMARTBIOGRID project (funded by the German Federal Ministry for Economic Affairs and Energy, FKZ: 03KB159B), FlixOpt has evolved from the Matlab-based flixOptMat framework while incorporating the best ideas from [oemof/solph](https://github.com/oemof/oemof-solph).
131
-
132
- ---
133
-
134
- ## 🌟 What Makes FlixOpt Different
135
-
136
- ### Start Simple, Scale Complex
137
- Define a working model in minutes with high-level components, then drill down to fine-grained control when needed. No rewriting, no framework switching.
138
-
139
- ```python
140
- import flixopt as fx
141
-
142
- # Simple start
143
- boiler = fx.Boiler("Boiler", eta=0.9, ...)
144
-
145
- # Advanced control when needed - extend with native linopy
146
- boiler.model.add_constraints(custom_constraint, name="my_constraint")
147
- ```
148
-
149
- ### Multi-Criteria Optimization Done Right
150
- Model costs, emissions, resource use, and any custom metric simultaneously as **Effects**. Optimize any single Effect, use weighted combinations, or apply ε-constraints:
151
-
152
- ```python
153
- costs = fx.Effect('costs', '€', 'Total costs',
154
- share_from_temporal={'CO2': 180}) # 180 €/tCO2
155
- co2 = fx.Effect('CO2', 'kg', 'Emissions', maximum_periodic=50000)
156
- ```
157
-
158
- ### Performance at Any Scale
159
- Choose the right calculation mode for your problem:
160
- - **Full** - Maximum accuracy for smaller problems
161
- - **Segmented** - Rolling horizon for large time series
162
- - **Aggregated** - Typical periods using [TSAM](https://github.com/FZJ-IEK3-VSA/tsam) for massive models
163
-
164
- ### Built for Reproducibility
165
- Every result file is self-contained with complete model information. Load it months later and know exactly what you optimized. Export to NetCDF, share with colleagues, archive for compliance.
166
-
167
- ---
168
-
169
- ## 🚀 Quick Start
170
-
171
- ```bash
172
- pip install flixopt
173
- ```
174
-
175
- That's it. FlixOpt comes with the [HiGHS](https://highs.dev/) solver included - you're ready to optimize.
176
- Many more solvers are supported (gurobi, cplex, cbc, glpk, ...)
177
-
178
- For additional features (interactive network visualization, time series aggregation):
179
- ```bash
180
- pip install "flixopt[full]"
181
- ```
182
-
183
- **Next steps:**
184
- - 📚 [Full Documentation](https://flixopt.github.io/flixopt/latest/)
185
- - 💡 [Examples](https://flixopt.github.io/flixopt/latest/examples/)
186
- - 🔧 [API Reference](https://flixopt.github.io/flixopt/latest/api-reference/)
187
-
188
- ---
189
-
190
- ## 🤝 Contributing
191
-
192
- FlixOpt thrives on community input. Whether you're fixing bugs, adding components, improving docs, or sharing use cases - we welcome your contributions.
193
-
194
- See our [contribution guide](https://flixopt.github.io/flixopt/latest/contribute/) to get started.
195
-
196
- ---
197
-
198
- ## 📖 Citation
199
-
200
- If FlixOpt supports your research or project, please cite:
201
-
202
- - **Main Citation:** [DOI:10.18086/eurosun.2022.04.07](https://doi.org/10.18086/eurosun.2022.04.07)
203
- - **Short Overview:** [DOI:10.13140/RG.2.2.14948.24969](https://doi.org/10.13140/RG.2.2.14948.24969)
204
-
205
- ---
206
-
207
- ## 📄 License
208
-
209
- MIT License - See [LICENSE](https://github.com/flixopt/flixopt/blob/main/LICENSE) for details.