flixopt 2.1.6__py3-none-any.whl → 2.1.8__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.
- docs/examples/00-Minimal Example.md +1 -1
- docs/examples/01-Basic Example.md +1 -1
- docs/examples/02-Complex Example.md +1 -1
- docs/examples/index.md +1 -1
- docs/faq/contribute.md +26 -14
- docs/faq/index.md +1 -1
- docs/javascripts/mathjax.js +1 -1
- docs/user-guide/Mathematical Notation/Bus.md +1 -1
- docs/user-guide/Mathematical Notation/Effects, Penalty & Objective.md +21 -21
- docs/user-guide/Mathematical Notation/Flow.md +3 -3
- docs/user-guide/Mathematical Notation/InvestParameters.md +3 -0
- docs/user-guide/Mathematical Notation/LinearConverter.md +5 -5
- docs/user-guide/Mathematical Notation/OnOffParameters.md +3 -0
- docs/user-guide/Mathematical Notation/Piecewise.md +1 -1
- docs/user-guide/Mathematical Notation/Storage.md +2 -2
- docs/user-guide/Mathematical Notation/index.md +1 -1
- docs/user-guide/Mathematical Notation/others.md +1 -1
- docs/user-guide/index.md +2 -2
- flixopt/__init__.py +4 -0
- flixopt/aggregation.py +33 -32
- flixopt/calculation.py +161 -65
- flixopt/components.py +687 -154
- flixopt/config.py +17 -8
- flixopt/core.py +69 -60
- flixopt/effects.py +146 -64
- flixopt/elements.py +297 -110
- flixopt/features.py +78 -71
- flixopt/flow_system.py +72 -50
- flixopt/interface.py +952 -113
- flixopt/io.py +15 -10
- flixopt/linear_converters.py +373 -81
- flixopt/network_app.py +445 -266
- flixopt/plotting.py +215 -87
- flixopt/results.py +382 -209
- flixopt/solvers.py +25 -21
- flixopt/structure.py +41 -39
- flixopt/utils.py +10 -7
- {flixopt-2.1.6.dist-info → flixopt-2.1.8.dist-info}/METADATA +64 -53
- flixopt-2.1.8.dist-info/RECORD +56 -0
- scripts/extract_release_notes.py +5 -5
- scripts/gen_ref_pages.py +1 -1
- flixopt-2.1.6.dist-info/RECORD +0 -54
- {flixopt-2.1.6.dist-info → flixopt-2.1.8.dist-info}/WHEEL +0 -0
- {flixopt-2.1.6.dist-info → flixopt-2.1.8.dist-info}/licenses/LICENSE +0 -0
- {flixopt-2.1.6.dist-info → flixopt-2.1.8.dist-info}/top_level.txt +0 -0
flixopt/solvers.py
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
This module contains the solvers of the flixopt framework, making them available to the end user in a compact way.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
5
7
|
import logging
|
|
6
8
|
from dataclasses import dataclass, field
|
|
7
|
-
from typing import Any, ClassVar
|
|
9
|
+
from typing import Any, ClassVar
|
|
8
10
|
|
|
9
11
|
logger = logging.getLogger('flixopt')
|
|
10
12
|
|
|
@@ -14,41 +16,42 @@ class _Solver:
|
|
|
14
16
|
"""
|
|
15
17
|
Abstract base class for solvers.
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
mip_gap
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
Args:
|
|
20
|
+
mip_gap: Acceptable relative optimality gap in [0.0, 1.0].
|
|
21
|
+
time_limit_seconds: Time limit in seconds.
|
|
22
|
+
extra_options: Additional solver options merged into `options`.
|
|
21
23
|
"""
|
|
22
24
|
|
|
23
25
|
name: ClassVar[str]
|
|
24
26
|
mip_gap: float
|
|
25
27
|
time_limit_seconds: int
|
|
26
|
-
extra_options:
|
|
28
|
+
extra_options: dict[str, Any] = field(default_factory=dict)
|
|
27
29
|
|
|
28
30
|
@property
|
|
29
|
-
def options(self) ->
|
|
31
|
+
def options(self) -> dict[str, Any]:
|
|
30
32
|
"""Return a dictionary of solver options."""
|
|
31
33
|
return {key: value for key, value in {**self._options, **self.extra_options}.items() if value is not None}
|
|
32
34
|
|
|
33
35
|
@property
|
|
34
|
-
def _options(self) ->
|
|
36
|
+
def _options(self) -> dict[str, Any]:
|
|
35
37
|
"""Return a dictionary of solver options, translated to the solver's API."""
|
|
36
38
|
raise NotImplementedError
|
|
37
39
|
|
|
38
40
|
|
|
39
41
|
class GurobiSolver(_Solver):
|
|
40
42
|
"""
|
|
43
|
+
Gurobi solver configuration.
|
|
44
|
+
|
|
41
45
|
Args:
|
|
42
|
-
mip_gap
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
extra_options (str): Filename for saving the solver log.
|
|
46
|
+
mip_gap: Acceptable relative optimality gap in [0.0, 1.0]; mapped to Gurobi `MIPGap`.
|
|
47
|
+
time_limit_seconds: Time limit in seconds; mapped to Gurobi `TimeLimit`.
|
|
48
|
+
extra_options: Additional solver options merged into `options`.
|
|
46
49
|
"""
|
|
47
50
|
|
|
48
51
|
name: ClassVar[str] = 'gurobi'
|
|
49
52
|
|
|
50
53
|
@property
|
|
51
|
-
def _options(self) ->
|
|
54
|
+
def _options(self) -> dict[str, Any]:
|
|
52
55
|
return {
|
|
53
56
|
'MIPGap': self.mip_gap,
|
|
54
57
|
'TimeLimit': self.time_limit_seconds,
|
|
@@ -57,19 +60,20 @@ class GurobiSolver(_Solver):
|
|
|
57
60
|
|
|
58
61
|
class HighsSolver(_Solver):
|
|
59
62
|
"""
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
extra_options
|
|
63
|
+
HiGHS solver configuration.
|
|
64
|
+
|
|
65
|
+
Attributes:
|
|
66
|
+
mip_gap: Acceptable relative optimality gap in [0.0, 1.0]; mapped to HiGHS `mip_rel_gap`.
|
|
67
|
+
time_limit_seconds: Time limit in seconds; mapped to HiGHS `time_limit`.
|
|
68
|
+
extra_options: Additional solver options merged into `options`.
|
|
69
|
+
threads (int | None): Number of threads to use. If None, HiGHS chooses.
|
|
66
70
|
"""
|
|
67
71
|
|
|
68
|
-
threads:
|
|
72
|
+
threads: int | None = None
|
|
69
73
|
name: ClassVar[str] = 'highs'
|
|
70
74
|
|
|
71
75
|
@property
|
|
72
|
-
def _options(self) ->
|
|
76
|
+
def _options(self) -> dict[str, Any]:
|
|
73
77
|
return {
|
|
74
78
|
'mip_rel_gap': self.mip_gap,
|
|
75
79
|
'time_limit': self.time_limit_seconds,
|
flixopt/structure.py
CHANGED
|
@@ -3,25 +3,28 @@ This module contains the core structure of the flixopt framework.
|
|
|
3
3
|
These classes are not directly used by the end user, but are used by other modules.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
6
8
|
import inspect
|
|
7
9
|
import json
|
|
8
10
|
import logging
|
|
9
|
-
import pathlib
|
|
10
11
|
from datetime import datetime
|
|
11
12
|
from io import StringIO
|
|
12
|
-
from typing import TYPE_CHECKING, Any,
|
|
13
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
13
14
|
|
|
14
15
|
import linopy
|
|
15
16
|
import numpy as np
|
|
16
|
-
import pandas as pd
|
|
17
17
|
import xarray as xr
|
|
18
18
|
from rich.console import Console
|
|
19
19
|
from rich.pretty import Pretty
|
|
20
20
|
|
|
21
|
-
from .
|
|
22
|
-
from .core import NumericData, Scalar, TimeSeries, TimeSeriesCollection, TimeSeriesData
|
|
21
|
+
from .core import TimeSeries, TimeSeriesData
|
|
23
22
|
|
|
24
23
|
if TYPE_CHECKING: # for type checking and preventing circular imports
|
|
24
|
+
import pathlib
|
|
25
|
+
|
|
26
|
+
import pandas as pd
|
|
27
|
+
|
|
25
28
|
from .effects import EffectCollectionModel
|
|
26
29
|
from .flow_system import FlowSystem
|
|
27
30
|
|
|
@@ -49,7 +52,7 @@ class SystemModel(linopy.Model):
|
|
|
49
52
|
It is used to create and store the variables and constraints for the flow_system.
|
|
50
53
|
"""
|
|
51
54
|
|
|
52
|
-
def __init__(self, flow_system:
|
|
55
|
+
def __init__(self, flow_system: FlowSystem):
|
|
53
56
|
"""
|
|
54
57
|
Args:
|
|
55
58
|
flow_system: The flow_system that is used to create the model.
|
|
@@ -57,7 +60,7 @@ class SystemModel(linopy.Model):
|
|
|
57
60
|
super().__init__(force_dim_names=True)
|
|
58
61
|
self.flow_system = flow_system
|
|
59
62
|
self.time_series_collection = flow_system.time_series_collection
|
|
60
|
-
self.effects:
|
|
63
|
+
self.effects: EffectCollectionModel | None = None
|
|
61
64
|
|
|
62
65
|
def do_modeling(self):
|
|
63
66
|
self.effects = self.flow_system.effects.create_model(self)
|
|
@@ -99,11 +102,11 @@ class SystemModel(linopy.Model):
|
|
|
99
102
|
return self.time_series_collection.hours_of_previous_timesteps
|
|
100
103
|
|
|
101
104
|
@property
|
|
102
|
-
def coords(self) ->
|
|
105
|
+
def coords(self) -> tuple[pd.DatetimeIndex]:
|
|
103
106
|
return (self.time_series_collection.timesteps,)
|
|
104
107
|
|
|
105
108
|
@property
|
|
106
|
-
def coords_extra(self) ->
|
|
109
|
+
def coords_extra(self) -> tuple[pd.DatetimeIndex]:
|
|
107
110
|
return (self.time_series_collection.timesteps_extra,)
|
|
108
111
|
|
|
109
112
|
|
|
@@ -112,11 +115,11 @@ class Interface:
|
|
|
112
115
|
This class is used to collect arguments about a Model. Its the base class for all Elements and Models in flixopt.
|
|
113
116
|
"""
|
|
114
117
|
|
|
115
|
-
def transform_data(self, flow_system:
|
|
118
|
+
def transform_data(self, flow_system: FlowSystem):
|
|
116
119
|
"""Transforms the data of the interface to match the FlowSystem's dimensions"""
|
|
117
120
|
raise NotImplementedError('Every Interface needs a transform_data() method')
|
|
118
121
|
|
|
119
|
-
def infos(self, use_numpy: bool = True, use_element_label: bool = False) ->
|
|
122
|
+
def infos(self, use_numpy: bool = True, use_element_label: bool = False) -> dict:
|
|
120
123
|
"""
|
|
121
124
|
Generate a dictionary representation of the object's constructor arguments.
|
|
122
125
|
Excludes default values and empty dictionaries and lists.
|
|
@@ -150,7 +153,7 @@ class Interface:
|
|
|
150
153
|
details[name] = copy_and_convert_datatypes(value, use_numpy, use_element_label)
|
|
151
154
|
return details
|
|
152
155
|
|
|
153
|
-
def to_json(self, path:
|
|
156
|
+
def to_json(self, path: str | pathlib.Path):
|
|
154
157
|
"""
|
|
155
158
|
Saves the element to a json file.
|
|
156
159
|
This not meant to be reloaded and recreate the object, but rather used to document or compare the object.
|
|
@@ -162,7 +165,7 @@ class Interface:
|
|
|
162
165
|
with open(path, 'w', encoding='utf-8') as f:
|
|
163
166
|
json.dump(data, f, indent=4, ensure_ascii=False)
|
|
164
167
|
|
|
165
|
-
def to_dict(self) ->
|
|
168
|
+
def to_dict(self) -> dict:
|
|
166
169
|
"""Convert the object to a dictionary representation."""
|
|
167
170
|
data = {'__class__': self.__class__.__name__}
|
|
168
171
|
|
|
@@ -200,7 +203,7 @@ class Interface:
|
|
|
200
203
|
return {k: self._serialize_value(v) for k, v in d.items()}
|
|
201
204
|
|
|
202
205
|
@classmethod
|
|
203
|
-
def _deserialize_dict(cls, data:
|
|
206
|
+
def _deserialize_dict(cls, data: dict) -> dict | Interface:
|
|
204
207
|
if '__class__' in data:
|
|
205
208
|
class_name = data.pop('__class__')
|
|
206
209
|
try:
|
|
@@ -217,7 +220,7 @@ class Interface:
|
|
|
217
220
|
return {k: cls._deserialize_value(v) for k, v in data.items()}
|
|
218
221
|
|
|
219
222
|
@classmethod
|
|
220
|
-
def _deserialize_list(cls, data:
|
|
223
|
+
def _deserialize_list(cls, data: list) -> list:
|
|
221
224
|
return [cls._deserialize_value(value) for value in data]
|
|
222
225
|
|
|
223
226
|
@classmethod
|
|
@@ -232,7 +235,7 @@ class Interface:
|
|
|
232
235
|
return value
|
|
233
236
|
|
|
234
237
|
@classmethod
|
|
235
|
-
def from_dict(cls, data:
|
|
238
|
+
def from_dict(cls, data: dict) -> Interface:
|
|
236
239
|
"""
|
|
237
240
|
Create an instance from a dictionary representation.
|
|
238
241
|
|
|
@@ -257,7 +260,7 @@ class Interface:
|
|
|
257
260
|
class Element(Interface):
|
|
258
261
|
"""This class is the basic Element of flixopt. Every Element has a label"""
|
|
259
262
|
|
|
260
|
-
def __init__(self, label: str, meta_data:
|
|
263
|
+
def __init__(self, label: str, meta_data: dict | None = None):
|
|
261
264
|
"""
|
|
262
265
|
Args:
|
|
263
266
|
label: The label of the element
|
|
@@ -265,13 +268,14 @@ class Element(Interface):
|
|
|
265
268
|
"""
|
|
266
269
|
self.label = Element._valid_label(label)
|
|
267
270
|
self.meta_data = meta_data if meta_data is not None else {}
|
|
268
|
-
self.model:
|
|
271
|
+
self.model: ElementModel | None = None
|
|
269
272
|
|
|
270
273
|
def _plausibility_checks(self) -> None:
|
|
271
|
-
"""This function is used to do some basic plausibility checks for each Element during initialization
|
|
274
|
+
"""This function is used to do some basic plausibility checks for each Element during initialization.
|
|
275
|
+
This is run after all data is transformed to the correct format/type"""
|
|
272
276
|
raise NotImplementedError('Every Element needs a _plausibility_checks() method')
|
|
273
277
|
|
|
274
|
-
def create_model(self, model: SystemModel) ->
|
|
278
|
+
def create_model(self, model: SystemModel) -> ElementModel:
|
|
275
279
|
raise NotImplementedError('Every Element needs a create_model() method')
|
|
276
280
|
|
|
277
281
|
@property
|
|
@@ -303,9 +307,7 @@ class Element(Interface):
|
|
|
303
307
|
class Model:
|
|
304
308
|
"""Stores Variables and Constraints."""
|
|
305
309
|
|
|
306
|
-
def __init__(
|
|
307
|
-
self, model: SystemModel, label_of_element: str, label: str = '', label_full: Optional[str] = None
|
|
308
|
-
):
|
|
310
|
+
def __init__(self, model: SystemModel, label_of_element: str, label: str = '', label_full: str | None = None):
|
|
309
311
|
"""
|
|
310
312
|
Args:
|
|
311
313
|
model: The SystemModel that is used to create the model.
|
|
@@ -318,21 +320,21 @@ class Model:
|
|
|
318
320
|
self._label = label
|
|
319
321
|
self._label_full = label_full
|
|
320
322
|
|
|
321
|
-
self._variables_direct:
|
|
322
|
-
self._constraints_direct:
|
|
323
|
-
self.sub_models:
|
|
323
|
+
self._variables_direct: list[str] = []
|
|
324
|
+
self._constraints_direct: list[str] = []
|
|
325
|
+
self.sub_models: list[Model] = []
|
|
324
326
|
|
|
325
|
-
self._variables_short:
|
|
326
|
-
self._constraints_short:
|
|
327
|
-
self._sub_models_short:
|
|
327
|
+
self._variables_short: dict[str, str] = {}
|
|
328
|
+
self._constraints_short: dict[str, str] = {}
|
|
329
|
+
self._sub_models_short: dict[str, str] = {}
|
|
328
330
|
logger.debug(f'Created {self.__class__.__name__} "{self.label_full}"')
|
|
329
331
|
|
|
330
332
|
def do_modeling(self):
|
|
331
333
|
raise NotImplementedError('Every Model needs a do_modeling() method')
|
|
332
334
|
|
|
333
335
|
def add(
|
|
334
|
-
self, item:
|
|
335
|
-
) ->
|
|
336
|
+
self, item: linopy.Variable | linopy.Constraint | Model, short_name: str | None = None
|
|
337
|
+
) -> linopy.Variable | linopy.Constraint | Model:
|
|
336
338
|
"""
|
|
337
339
|
Add a variable, constraint or sub-model to the model
|
|
338
340
|
|
|
@@ -358,8 +360,8 @@ class Model:
|
|
|
358
360
|
|
|
359
361
|
def filter_variables(
|
|
360
362
|
self,
|
|
361
|
-
filter_by:
|
|
362
|
-
length: Literal['scalar', 'time'] = None,
|
|
363
|
+
filter_by: Literal['binary', 'continuous', 'integer'] | None = None,
|
|
364
|
+
length: Literal['scalar', 'time'] | None = None,
|
|
363
365
|
):
|
|
364
366
|
if filter_by is None:
|
|
365
367
|
all_variables = self.variables
|
|
@@ -401,7 +403,7 @@ class Model:
|
|
|
401
403
|
return self._model.constraints[self._constraints_direct]
|
|
402
404
|
|
|
403
405
|
@property
|
|
404
|
-
def _variables(self) ->
|
|
406
|
+
def _variables(self) -> list[str]:
|
|
405
407
|
all_variables = self._variables_direct.copy()
|
|
406
408
|
for sub_model in self.sub_models:
|
|
407
409
|
for variable in sub_model._variables:
|
|
@@ -413,7 +415,7 @@ class Model:
|
|
|
413
415
|
return all_variables
|
|
414
416
|
|
|
415
417
|
@property
|
|
416
|
-
def _constraints(self) ->
|
|
418
|
+
def _constraints(self) -> list[str]:
|
|
417
419
|
all_constraints = self._constraints_direct.copy()
|
|
418
420
|
for sub_model in self.sub_models:
|
|
419
421
|
for constraint in sub_model._constraints:
|
|
@@ -431,7 +433,7 @@ class Model:
|
|
|
431
433
|
return self._model.constraints[self._constraints]
|
|
432
434
|
|
|
433
435
|
@property
|
|
434
|
-
def all_sub_models(self) ->
|
|
436
|
+
def all_sub_models(self) -> list[Model]:
|
|
435
437
|
return [model for sub_model in self.sub_models for model in [sub_model] + sub_model.all_sub_models]
|
|
436
438
|
|
|
437
439
|
|
|
@@ -549,7 +551,7 @@ def copy_and_convert_datatypes(data: Any, use_numpy: bool = True, use_element_la
|
|
|
549
551
|
raise TypeError(f'copy_and_convert_datatypes() did get unexpected data of type "{type(data)}": {data=}')
|
|
550
552
|
|
|
551
553
|
|
|
552
|
-
def get_compact_representation(data: Any, array_threshold: int = 50, decimals: int = 2) ->
|
|
554
|
+
def get_compact_representation(data: Any, array_threshold: int = 50, decimals: int = 2) -> dict:
|
|
553
555
|
"""
|
|
554
556
|
Generate a compact json serializable representation of deeply nested data.
|
|
555
557
|
Numpy arrays are statistically described if they exceed a threshold and converted to lists.
|
|
@@ -560,7 +562,7 @@ def get_compact_representation(data: Any, array_threshold: int = 50, decimals: i
|
|
|
560
562
|
decimals (int): Number of decimal places in which to describe the arrays.
|
|
561
563
|
|
|
562
564
|
Returns:
|
|
563
|
-
|
|
565
|
+
dict: A dictionary representation of the data
|
|
564
566
|
"""
|
|
565
567
|
|
|
566
568
|
def format_np_array_if_found(value: Any) -> Any:
|
|
@@ -579,7 +581,7 @@ def get_compact_representation(data: Any, array_threshold: int = 50, decimals: i
|
|
|
579
581
|
)
|
|
580
582
|
return value
|
|
581
583
|
|
|
582
|
-
def describe_numpy_arrays(arr: np.ndarray) ->
|
|
584
|
+
def describe_numpy_arrays(arr: np.ndarray) -> str | list:
|
|
583
585
|
"""Shortens NumPy arrays if they exceed the specified length."""
|
|
584
586
|
|
|
585
587
|
def normalized_center_of_mass(array: Any) -> float:
|
flixopt/utils.py
CHANGED
|
@@ -2,21 +2,24 @@
|
|
|
2
2
|
This module contains several utility functions used throughout the flixopt framework.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
5
7
|
import logging
|
|
6
|
-
from typing import
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
import
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
import numpy as np
|
|
12
|
+
import xarray as xr
|
|
10
13
|
|
|
11
14
|
logger = logging.getLogger('flixopt')
|
|
12
15
|
|
|
13
16
|
|
|
14
|
-
def is_number(number_alias:
|
|
15
|
-
"""Returns True
|
|
17
|
+
def is_number(number_alias: int | float | str) -> bool:
|
|
18
|
+
"""Returns True if value is a number or a number-like string."""
|
|
16
19
|
try:
|
|
17
20
|
float(number_alias)
|
|
18
21
|
return True
|
|
19
|
-
except ValueError:
|
|
22
|
+
except (ValueError, TypeError):
|
|
20
23
|
return False
|
|
21
24
|
|
|
22
25
|
|
|
@@ -32,7 +35,7 @@ def round_floats(obj, decimals=2):
|
|
|
32
35
|
|
|
33
36
|
def convert_dataarray(
|
|
34
37
|
data: xr.DataArray, mode: Literal['py', 'numpy', 'xarray', 'structure']
|
|
35
|
-
) ->
|
|
38
|
+
) -> list[Any] | np.ndarray | xr.DataArray | str:
|
|
36
39
|
"""
|
|
37
40
|
Convert a DataArray to a different format.
|
|
38
41
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flixopt
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.8
|
|
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>
|
|
@@ -18,58 +18,64 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
18
18
|
Classifier: Intended Audience :: Developers
|
|
19
19
|
Classifier: Intended Audience :: Science/Research
|
|
20
20
|
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
21
22
|
Requires-Python: >=3.10
|
|
22
23
|
Description-Content-Type: text/markdown
|
|
23
24
|
License-File: LICENSE
|
|
24
25
|
Requires-Dist: numpy<3,>=1.21.5
|
|
25
26
|
Requires-Dist: pandas<3,>=2.0.0
|
|
26
|
-
Requires-Dist:
|
|
27
|
+
Requires-Dist: xarray<2026.0,>=2024.2.0
|
|
28
|
+
Requires-Dist: linopy<0.6,>=0.5.1
|
|
27
29
|
Requires-Dist: netcdf4<2,>=1.6.1
|
|
28
|
-
Requires-Dist:
|
|
29
|
-
Requires-Dist: rich
|
|
30
|
-
Requires-Dist: tomli
|
|
31
|
-
Requires-Dist: highspy
|
|
32
|
-
Requires-Dist: matplotlib<4
|
|
33
|
-
Requires-Dist: plotly<
|
|
30
|
+
Requires-Dist: pyyaml<7,>=6.0.0
|
|
31
|
+
Requires-Dist: rich<15,>=13.0.0
|
|
32
|
+
Requires-Dist: tomli<3,>=2.0.1; python_version < "3.11"
|
|
33
|
+
Requires-Dist: highspy<2,>=1.5.3
|
|
34
|
+
Requires-Dist: matplotlib<4,>=3.5.2
|
|
35
|
+
Requires-Dist: plotly<7,>=5.15.0
|
|
34
36
|
Provides-Extra: network-viz
|
|
35
|
-
Requires-Dist: dash
|
|
36
|
-
Requires-Dist: dash-cytoscape
|
|
37
|
-
Requires-Dist: dash-daq
|
|
38
|
-
Requires-Dist: networkx
|
|
39
|
-
Requires-Dist: werkzeug
|
|
37
|
+
Requires-Dist: dash<4,>=3.0.0; extra == "network-viz"
|
|
38
|
+
Requires-Dist: dash-cytoscape<2,>=1.0.0; extra == "network-viz"
|
|
39
|
+
Requires-Dist: dash-daq<1,>=0.6.0; extra == "network-viz"
|
|
40
|
+
Requires-Dist: networkx<4,>=3.0.0; extra == "network-viz"
|
|
41
|
+
Requires-Dist: werkzeug<4,>=3.0.0; extra == "network-viz"
|
|
42
|
+
Requires-Dist: flask<4,>=3.0.0; extra == "network-viz"
|
|
40
43
|
Provides-Extra: full
|
|
41
|
-
Requires-Dist: pyvis==0.3.
|
|
42
|
-
Requires-Dist: tsam<3
|
|
43
|
-
Requires-Dist: scipy<2
|
|
44
|
-
Requires-Dist: gurobipy
|
|
45
|
-
Requires-Dist: dash
|
|
46
|
-
Requires-Dist: dash-cytoscape
|
|
47
|
-
Requires-Dist: dash-daq
|
|
48
|
-
Requires-Dist: networkx
|
|
49
|
-
Requires-Dist: werkzeug
|
|
44
|
+
Requires-Dist: pyvis==0.3.2; extra == "full"
|
|
45
|
+
Requires-Dist: tsam<3,>=2.3.1; extra == "full"
|
|
46
|
+
Requires-Dist: scipy<2,>=1.15.1; extra == "full"
|
|
47
|
+
Requires-Dist: gurobipy<13,>=10.0.0; extra == "full"
|
|
48
|
+
Requires-Dist: dash<4,>=3.0.0; extra == "full"
|
|
49
|
+
Requires-Dist: dash-cytoscape<2,>=1.0.0; extra == "full"
|
|
50
|
+
Requires-Dist: dash-daq<1,>=0.6.0; extra == "full"
|
|
51
|
+
Requires-Dist: networkx<4,>=3.0.0; extra == "full"
|
|
52
|
+
Requires-Dist: werkzeug<4,>=3.0.0; extra == "full"
|
|
53
|
+
Requires-Dist: flask<4,>=3.0.0; extra == "full"
|
|
50
54
|
Provides-Extra: dev
|
|
51
|
-
Requires-Dist: pytest
|
|
52
|
-
Requires-Dist:
|
|
53
|
-
Requires-Dist:
|
|
54
|
-
Requires-Dist:
|
|
55
|
-
Requires-Dist:
|
|
56
|
-
Requires-Dist:
|
|
57
|
-
Requires-Dist:
|
|
58
|
-
Requires-Dist:
|
|
59
|
-
Requires-Dist: dash
|
|
60
|
-
Requires-Dist:
|
|
61
|
-
Requires-Dist:
|
|
55
|
+
Requires-Dist: pytest==8.4.2; extra == "dev"
|
|
56
|
+
Requires-Dist: nbformat==5.10.4; extra == "dev"
|
|
57
|
+
Requires-Dist: ruff==0.13.0; 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.1; 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"
|
|
62
68
|
Provides-Extra: docs
|
|
63
|
-
Requires-Dist: mkdocs-material
|
|
64
|
-
Requires-Dist: mkdocstrings-python
|
|
65
|
-
Requires-Dist: mkdocs-table-reader-plugin
|
|
66
|
-
Requires-Dist: mkdocs-gen-files
|
|
67
|
-
Requires-Dist: mkdocs-include-markdown-plugin
|
|
68
|
-
Requires-Dist: mkdocs-literate-nav
|
|
69
|
-
Requires-Dist: markdown-include
|
|
70
|
-
Requires-Dist: pymdown-extensions
|
|
71
|
-
Requires-Dist: pygments
|
|
72
|
-
Requires-Dist: mike
|
|
69
|
+
Requires-Dist: mkdocs-material==9.6.19; 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"
|
|
73
79
|
Dynamic: license-file
|
|
74
80
|
|
|
75
81
|
# FlixOpt: Energy and Material Flow Optimization Framework
|
|
@@ -92,7 +98,7 @@ Dynamic: license-file
|
|
|
92
98
|
|
|
93
99
|
**flixopt** provides a user-friendly interface with options for advanced users.
|
|
94
100
|
|
|
95
|
-
It was originally developed by [TU Dresden](https://github.com/gewv-tu-dresden) as part of the SMARTBIOGRID project, funded by the German Federal Ministry for Economic Affairs and Energy (FKZ: 03KB159B). Building on the Matlab-based flixOptMat framework (developed in the FAKS project), FlixOpt also incorporates concepts from [oemof/solph](https://github.com/oemof/oemof-solph).
|
|
101
|
+
It was originally developed by [TU Dresden](https://github.com/gewv-tu-dresden) as part of the SMARTBIOGRID project, funded by the German Federal Ministry for Economic Affairs and Energy (FKZ: 03KB159B). Building on the Matlab-based flixOptMat framework (developed in the FAKS project), FlixOpt also incorporates concepts from [oemof/solph](https://github.com/oemof/oemof-solph).
|
|
96
102
|
|
|
97
103
|
---
|
|
98
104
|
|
|
@@ -117,7 +123,7 @@ It was originally developed by [TU Dresden](https://github.com/gewv-tu-dresden)
|
|
|
117
123
|
|
|
118
124
|
- **Calculation Modes**
|
|
119
125
|
- **Full** - Solve the model with highest accuracy and computational requirements.
|
|
120
|
-
- **Segmented** - Speed up solving by using a rolling horizon.
|
|
126
|
+
- **Segmented** - Speed up solving by using a rolling horizon.
|
|
121
127
|
- **Aggregated** - Speed up solving by identifying typical periods using [TSAM](https://github.com/FZJ-IEK3-VSA/tsam). Suitable for large models.
|
|
122
128
|
|
|
123
129
|
---
|
|
@@ -139,22 +145,27 @@ The documentation is available at [https://flixopt.github.io/flixopt/latest/](ht
|
|
|
139
145
|
|
|
140
146
|
---
|
|
141
147
|
|
|
142
|
-
##
|
|
148
|
+
## 🎯️ Solver Integration
|
|
143
149
|
|
|
144
|
-
By default, FlixOpt uses the open-source solver [HiGHS](https://highs.dev/) which is installed by default. However, it is compatible with additional solvers such as:
|
|
150
|
+
By default, FlixOpt uses the open-source solver [HiGHS](https://highs.dev/) which is installed by default. However, it is compatible with additional solvers such as:
|
|
145
151
|
|
|
146
|
-
- [Gurobi](https://www.gurobi.com/)
|
|
147
|
-
- [CBC](https://github.com/coin-or/Cbc)
|
|
152
|
+
- [Gurobi](https://www.gurobi.com/)
|
|
153
|
+
- [CBC](https://github.com/coin-or/Cbc)
|
|
148
154
|
- [GLPK](https://www.gnu.org/software/glpk/)
|
|
149
155
|
- [CPLEX](https://www.ibm.com/analytics/cplex-optimizer)
|
|
150
156
|
|
|
151
|
-
For detailed licensing and installation instructions, refer to the respective solver documentation.
|
|
157
|
+
For detailed licensing and installation instructions, refer to the respective solver documentation.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 🛠 Development Setup
|
|
162
|
+
Look into our docs for [development setup](https://flixopt.github.io/flixopt/latest/contribute/)
|
|
152
163
|
|
|
153
164
|
---
|
|
154
165
|
|
|
155
166
|
## 📖 Citation
|
|
156
167
|
|
|
157
|
-
If you use FlixOpt in your research or project, please cite the following:
|
|
168
|
+
If you use FlixOpt in your research or project, please cite the following:
|
|
158
169
|
|
|
159
|
-
- **Main Citation:** [DOI:10.18086/eurosun.2022.04.07](https://doi.org/10.18086/eurosun.2022.04.07)
|
|
160
|
-
- **Short Overview:** [DOI:10.13140/RG.2.2.14948.24969](https://doi.org/10.13140/RG.2.2.14948.24969)
|
|
170
|
+
- **Main Citation:** [DOI:10.18086/eurosun.2022.04.07](https://doi.org/10.18086/eurosun.2022.04.07)
|
|
171
|
+
- **Short Overview:** [DOI:10.13140/RG.2.2.14948.24969](https://doi.org/10.13140/RG.2.2.14948.24969)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
docs/examples/00-Minimal Example.md,sha256=TjtnI8o96YNOCFwRC8BSXFGoVqfB53BtvOG4b29FwkQ,80
|
|
2
|
+
docs/examples/01-Basic Example.md,sha256=sZHonC6A_wtZ2IEy_6BAMY8wViyIcivmcj8GYIZ_qck,78
|
|
3
|
+
docs/examples/02-Complex Example.md,sha256=5cczYkXFpzpQTNp9dkmOEdTXxoWLETKty417q6MyT8s,287
|
|
4
|
+
docs/examples/03-Calculation Modes.md,sha256=FZPBXmrkir6QhQsiXwWp2sOOntIIkODCgh3lVqOrP6w,231
|
|
5
|
+
docs/examples/index.md,sha256=KwXrsxxiHk563bny4I4B2X_CfPNiSXx8TsfI671MLdg,179
|
|
6
|
+
docs/faq/contribute.md,sha256=CL7Z85zyPes1Kl16_8oWLU2RTTbMdPfhmvt4tsnkikU,2508
|
|
7
|
+
docs/faq/index.md,sha256=MH_SPZllm_5npxPP6DHXbJlpLXZc-nbWTFJvMmZYz9Q,50
|
|
8
|
+
docs/images/architecture_flixOpt-pre2.0.0.png,sha256=9RWSA3vys588aadr2437zor-_-xBTQNQ0bAf8xGcu5g,70605
|
|
9
|
+
docs/images/architecture_flixOpt.png,sha256=KjN1bJwESbkHmTW7UsJ7dZyiKZlTO7Dx20dg8KlR1HU,260219
|
|
10
|
+
docs/images/flixopt-icon.svg,sha256=_1a6bk2pDOVEy233LC1nM6jZ35NdzD8Hd3UqGxW1Xpg,135341
|
|
11
|
+
docs/javascripts/mathjax.js,sha256=LJDaO5MM_5W8gI5-S5SiZ17qeMgeoVJO-inMyBNy7UE,402
|
|
12
|
+
docs/user-guide/index.md,sha256=TBO7lk13M95w2A9WiT5asfZn9oU9GZ1O0XW9eUm5GLo,7450
|
|
13
|
+
docs/user-guide/Mathematical Notation/Bus.md,sha256=pqjGa3PZBSmuO4YR44bK21bMmRcWC8dkzP3z0XX-PJw,1613
|
|
14
|
+
"docs/user-guide/Mathematical Notation/Effects, Penalty & Objective.md",sha256=vXQWt-UyITOVTJWPkKfjJzucbyml2OTQ6URQiMoc9dU,5671
|
|
15
|
+
docs/user-guide/Mathematical Notation/Flow.md,sha256=zxCp02o0t2EwB-hlwGtmh8aQveRGgcgwqMN8MvLxaI0,1099
|
|
16
|
+
docs/user-guide/Mathematical Notation/InvestParameters.md,sha256=UeuCpAyhOfDS2C3efmi_2EFkaFBK7HcqhHeBXl9BhFw,48
|
|
17
|
+
docs/user-guide/Mathematical Notation/LinearConverter.md,sha256=mKYbpnYxXW9xI2ybVfAyxDJdwahnj7L9ZTY0mnq3_l0,1321
|
|
18
|
+
docs/user-guide/Mathematical Notation/OnOffParameters.md,sha256=QEgxhqb53VlyBifIdExwaQpsdeE0Cyb8aN3-aCHQ21U,47
|
|
19
|
+
docs/user-guide/Mathematical Notation/Piecewise.md,sha256=GgTQ7dVTTb0lq14GFuuZeGYrUXtMy1wkztJLIVchchw,1993
|
|
20
|
+
docs/user-guide/Mathematical Notation/Storage.md,sha256=-QiZN2vA-f-P8JGkQDPYBdt2xt6J0Z2jbKDuk6j-rIs,2201
|
|
21
|
+
docs/user-guide/Mathematical Notation/index.md,sha256=2d6k4zbKET1kg7zBt1fEdKsG8jM5j2IIe6yclMTUlDw,1254
|
|
22
|
+
docs/user-guide/Mathematical Notation/others.md,sha256=z6LOzcnvfI-1qQx0Fg7Q6wSK9tAzH2d34KbW4lYNyCE,48
|
|
23
|
+
flixopt/__init__.py,sha256=xTxHXC-_lWa65roGUM3J3HXfiYcMCJHoQsuL5mS0Xkg,688
|
|
24
|
+
flixopt/aggregation.py,sha256=BFy2ngr0a0By5wfBZet9fX8X5ZPmkn1x6HMRaw1ZsTo,16892
|
|
25
|
+
flixopt/calculation.py,sha256=VBcvpQr7ZXvWZfryfilwUzK161br4ZP3zTwvYHraGjY,24476
|
|
26
|
+
flixopt/commons.py,sha256=ZNlUN1z-h9OGHPo-s-n5OLlJaoPZKVGcAdRyGKpMk4M,1256
|
|
27
|
+
flixopt/components.py,sha256=efUwx_eqgVPsQEn8u0HUrgkvU2eU2tgv7wKwT2eeX_I,54632
|
|
28
|
+
flixopt/config.py,sha256=2GJ9NZl35OKMUvofIpztgKh3kdca1m1wa77RjsUaob0,9509
|
|
29
|
+
flixopt/config.yaml,sha256=imzAnnhcJhIfKNTTXFB5Td7Pvk5ARn5j720k-oGGRug,392
|
|
30
|
+
flixopt/core.py,sha256=HnXnUXnAL8yqBExdsXGgwu5HnfWRH0omjjMKgp_SBKc,37824
|
|
31
|
+
flixopt/effects.py,sha256=HcalPMUaAfuzD2p1OeQ9nLY2vmHv_GxwyGLLeqNGNZ8,19435
|
|
32
|
+
flixopt/elements.py,sha256=IWtr0zyS1GEttYMiBZxC6sEX7y8pCWEbySxok3nDxwI,33535
|
|
33
|
+
flixopt/features.py,sha256=m61ixTFJ_Jh-Emx6QKVxo04Heswm89XsPUqbH8ezNr8,43891
|
|
34
|
+
flixopt/flow_system.py,sha256=qvR4uktXERDKCI40w9tJidkWxt5B36XVoebCw5bJons,20886
|
|
35
|
+
flixopt/interface.py,sha256=e5tom-aTEPfl4FQg8abyDv7g1tTvxeOWiSWg_IGti-g,47575
|
|
36
|
+
flixopt/io.py,sha256=BziCFlHfqx1kWFBhr1EZi-odZaqTVZdfmHhl-_rf5Ug,11367
|
|
37
|
+
flixopt/linear_converters.py,sha256=rKa0AZlJHgDsPF_LVsvrhxhsmVTRanPE0NuKP7OICtg,22668
|
|
38
|
+
flixopt/network_app.py,sha256=JlEbufeg3WK89ILwz2gXq6xdZzHEo5urIcz1eBpgJyc,29456
|
|
39
|
+
flixopt/plotting.py,sha256=cGM8f5QDMOkKuBapgD6-EhN1X-f5WkDqyoxGPberjzI,59661
|
|
40
|
+
flixopt/results.py,sha256=121FoO3WrAuHm18_-OP93_-9JxuCVVm5JWvmC33P3-8,40682
|
|
41
|
+
flixopt/solvers.py,sha256=m38Smc22MJfHYMiqfNf1MA3OmvbTRm5OWS9nECkDdQk,2355
|
|
42
|
+
flixopt/structure.py,sha256=vyD1lc80NH3JLexKJuar9btgHhEbcNEmihCQkBWea8k,26254
|
|
43
|
+
flixopt/utils.py,sha256=a-YKR7C7HtD8dSIcxzlJTgryV5HMS7zELSXNYr_Lz9Q,1775
|
|
44
|
+
flixopt-2.1.8.dist-info/licenses/LICENSE,sha256=HKsZnbrM_3Rvnr_u9cWSG90cBsj5_slaqI_z_qcxnGI,1118
|
|
45
|
+
pics/architecture_flixOpt-pre2.0.0.png,sha256=9RWSA3vys588aadr2437zor-_-xBTQNQ0bAf8xGcu5g,70605
|
|
46
|
+
pics/architecture_flixOpt.png,sha256=KjN1bJwESbkHmTW7UsJ7dZyiKZlTO7Dx20dg8KlR1HU,260219
|
|
47
|
+
pics/flixOpt_plotting.jpg,sha256=zn7ZPAtXm5eRTxtOj86e4-PPhHpCar1jqGh7vMBgQGY,518862
|
|
48
|
+
pics/flixopt-icon.svg,sha256=_1a6bk2pDOVEy233LC1nM6jZ35NdzD8Hd3UqGxW1Xpg,135341
|
|
49
|
+
pics/pics.pptx,sha256=ImWeGGvjtWJ6BGruipsnZYmWtHj5sWdbw1NSFePbkC8,683344
|
|
50
|
+
scripts/extract_release_notes.py,sha256=3UUE4hWhdd2t2m2x0ZpchGP-A0MvfqO2Wc5EdNN-fgE,1249
|
|
51
|
+
scripts/gen_ref_pages.py,sha256=7bxRu2VfqFrnr7wln1BjMAqpQUzuTkLPJSBh83uikIQ,1948
|
|
52
|
+
tests/ressources/Zeitreihen2020.csv,sha256=kbsDTKZS0iUsNZAS7m3DohzZI_OHHWe44s3GwLvcTLw,1918412
|
|
53
|
+
flixopt-2.1.8.dist-info/METADATA,sha256=OMNIQF_kyzEFA1H3d-IUWwEEL84bG4t8KfS2nbW-TTU,8432
|
|
54
|
+
flixopt-2.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
55
|
+
flixopt-2.1.8.dist-info/top_level.txt,sha256=DEuo4R1z7GmEp5R3pjbQEJbaPRjKHFvNX2ceiBnVOL0,32
|
|
56
|
+
flixopt-2.1.8.dist-info/RECORD,,
|
scripts/extract_release_notes.py
CHANGED
|
@@ -11,10 +11,10 @@ from pathlib import Path
|
|
|
11
11
|
|
|
12
12
|
def extract_release_notes(version: str) -> str:
|
|
13
13
|
"""Extract release notes for a specific version from CHANGELOG.md"""
|
|
14
|
-
changelog_path = Path(
|
|
14
|
+
changelog_path = Path('CHANGELOG.md')
|
|
15
15
|
|
|
16
16
|
if not changelog_path.exists():
|
|
17
|
-
print(
|
|
17
|
+
print('❌ Error: CHANGELOG.md not found', file=sys.stderr)
|
|
18
18
|
sys.exit(1)
|
|
19
19
|
|
|
20
20
|
content = changelog_path.read_text(encoding='utf-8')
|
|
@@ -32,8 +32,8 @@ def extract_release_notes(version: str) -> str:
|
|
|
32
32
|
|
|
33
33
|
def main():
|
|
34
34
|
if len(sys.argv) != 2:
|
|
35
|
-
print(
|
|
36
|
-
print(
|
|
35
|
+
print('Usage: python extract_release_notes.py <version>')
|
|
36
|
+
print('Example: python extract_release_notes.py 2.1.2')
|
|
37
37
|
sys.exit(1)
|
|
38
38
|
|
|
39
39
|
version = sys.argv[1]
|
|
@@ -41,5 +41,5 @@ def main():
|
|
|
41
41
|
print(release_notes)
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
if __name__ ==
|
|
44
|
+
if __name__ == '__main__':
|
|
45
45
|
main()
|