flixopt 2.1.1__py3-none-any.whl → 2.2.0b0__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/release-notes/v2.2.0.md +55 -0
- docs/user-guide/Mathematical Notation/Investment.md +115 -0
- flixopt/calculation.py +65 -37
- flixopt/components.py +115 -73
- flixopt/core.py +966 -451
- flixopt/effects.py +269 -65
- flixopt/elements.py +79 -49
- flixopt/features.py +134 -85
- flixopt/flow_system.py +99 -16
- flixopt/interface.py +142 -51
- flixopt/io.py +56 -27
- flixopt/linear_converters.py +3 -3
- flixopt/plotting.py +34 -16
- flixopt/results.py +806 -108
- flixopt/structure.py +64 -10
- flixopt/utils.py +6 -9
- {flixopt-2.1.1.dist-info → flixopt-2.2.0b0.dist-info}/METADATA +1 -1
- {flixopt-2.1.1.dist-info → flixopt-2.2.0b0.dist-info}/RECORD +21 -21
- {flixopt-2.1.1.dist-info → flixopt-2.2.0b0.dist-info}/WHEEL +1 -1
- {flixopt-2.1.1.dist-info → flixopt-2.2.0b0.dist-info}/top_level.txt +0 -1
- docs/release-notes/v2.1.1.md +0 -11
- site/release-notes/_template.txt +0 -32
- {flixopt-2.1.1.dist-info → flixopt-2.2.0b0.dist-info}/licenses/LICENSE +0 -0
flixopt/structure.py
CHANGED
|
@@ -19,7 +19,7 @@ from rich.console import Console
|
|
|
19
19
|
from rich.pretty import Pretty
|
|
20
20
|
|
|
21
21
|
from .config import CONFIG
|
|
22
|
-
from .core import
|
|
22
|
+
from .core import Scalar, TimeSeries, TimeSeriesCollection, TimeSeriesData, TimestepData
|
|
23
23
|
|
|
24
24
|
if TYPE_CHECKING: # for type checking and preventing circular imports
|
|
25
25
|
from .effects import EffectCollectionModel
|
|
@@ -58,6 +58,7 @@ class SystemModel(linopy.Model):
|
|
|
58
58
|
self.flow_system = flow_system
|
|
59
59
|
self.time_series_collection = flow_system.time_series_collection
|
|
60
60
|
self.effects: Optional[EffectCollectionModel] = None
|
|
61
|
+
self.scenario_weights = self._calculate_scenario_weights(flow_system.scenario_weights)
|
|
61
62
|
|
|
62
63
|
def do_modeling(self):
|
|
63
64
|
self.effects = self.flow_system.effects.create_model(self)
|
|
@@ -69,6 +70,24 @@ class SystemModel(linopy.Model):
|
|
|
69
70
|
for bus_model in bus_models: # Buses after Components, because FlowModels are created in ComponentModels
|
|
70
71
|
bus_model.do_modeling()
|
|
71
72
|
|
|
73
|
+
def _calculate_scenario_weights(self, weights: Optional[TimeSeries] = None) -> xr.DataArray:
|
|
74
|
+
"""Calculates the weights of the scenarios. If None, all scenarios have the same weight. All weights are normalized to 1.
|
|
75
|
+
If no scenarios are present, s single weight of 1 is returned.
|
|
76
|
+
"""
|
|
77
|
+
if weights is not None and not isinstance(weights, TimeSeries):
|
|
78
|
+
raise TypeError(f'Weights must be a TimeSeries or None, got {type(weights)}')
|
|
79
|
+
if self.time_series_collection.scenarios is None:
|
|
80
|
+
return xr.DataArray(1)
|
|
81
|
+
if weights is None:
|
|
82
|
+
weights = xr.DataArray(
|
|
83
|
+
np.ones(len(self.time_series_collection.scenarios)),
|
|
84
|
+
coords={'scenario': self.time_series_collection.scenarios}
|
|
85
|
+
)
|
|
86
|
+
elif isinstance(weights, TimeSeries):
|
|
87
|
+
weights = weights.selected_data
|
|
88
|
+
|
|
89
|
+
return weights / weights.sum()
|
|
90
|
+
|
|
72
91
|
@property
|
|
73
92
|
def solution(self):
|
|
74
93
|
solution = super().solution
|
|
@@ -87,6 +106,10 @@ class SystemModel(linopy.Model):
|
|
|
87
106
|
effect.label_full: effect.model.results_structure()
|
|
88
107
|
for effect in sorted(self.flow_system.effects, key=lambda effect: effect.label_full.upper())
|
|
89
108
|
},
|
|
109
|
+
'Flows': {
|
|
110
|
+
flow.label_full: flow.model.results_structure()
|
|
111
|
+
for flow in sorted(self.flow_system.flows.values(), key=lambda flow: flow.label_full.upper())
|
|
112
|
+
},
|
|
90
113
|
}
|
|
91
114
|
return solution.reindex(time=self.time_series_collection.timesteps_extra)
|
|
92
115
|
|
|
@@ -98,13 +121,40 @@ class SystemModel(linopy.Model):
|
|
|
98
121
|
def hours_of_previous_timesteps(self):
|
|
99
122
|
return self.time_series_collection.hours_of_previous_timesteps
|
|
100
123
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
124
|
+
def get_coords(
|
|
125
|
+
self, scenario_dim=True, time_dim=True, extra_timestep=False
|
|
126
|
+
) -> Optional[Union[Tuple[pd.Index], Tuple[pd.Index, pd.Index]]]:
|
|
127
|
+
"""
|
|
128
|
+
Returns the coordinates of the model
|
|
104
129
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
130
|
+
Args:
|
|
131
|
+
scenario_dim: If True, the scenario dimension is included in the coordinates
|
|
132
|
+
time_dim: If True, the time dimension is included in the coordinates
|
|
133
|
+
extra_timestep: If True, the extra timesteps are used instead of the regular timesteps
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
The coordinates of the model. Might also be None if no scenarios are present and time_dim is False
|
|
137
|
+
"""
|
|
138
|
+
if not scenario_dim and not time_dim:
|
|
139
|
+
return None
|
|
140
|
+
scenarios = self.time_series_collection.scenarios
|
|
141
|
+
timesteps = (
|
|
142
|
+
self.time_series_collection.timesteps if not extra_timestep else self.time_series_collection.timesteps_extra
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
if scenario_dim and time_dim:
|
|
146
|
+
if scenarios is None:
|
|
147
|
+
return (timesteps,)
|
|
148
|
+
return timesteps, scenarios
|
|
149
|
+
|
|
150
|
+
if scenario_dim and not time_dim:
|
|
151
|
+
if scenarios is None:
|
|
152
|
+
return None
|
|
153
|
+
return (scenarios,)
|
|
154
|
+
if time_dim and not scenario_dim:
|
|
155
|
+
return (timesteps,)
|
|
156
|
+
|
|
157
|
+
raise ValueError(f'Cannot get coordinates with both {scenario_dim=} and {time_dim=}')
|
|
108
158
|
|
|
109
159
|
|
|
110
160
|
class Interface:
|
|
@@ -449,8 +499,7 @@ class ElementModel(Model):
|
|
|
449
499
|
|
|
450
500
|
def results_structure(self):
|
|
451
501
|
return {
|
|
452
|
-
'label': self.
|
|
453
|
-
'label_full': self.label_full,
|
|
502
|
+
'label': self.label_full,
|
|
454
503
|
'variables': list(self.variables),
|
|
455
504
|
'constraints': list(self.constraints),
|
|
456
505
|
}
|
|
@@ -534,9 +583,12 @@ def copy_and_convert_datatypes(data: Any, use_numpy: bool = True, use_element_la
|
|
|
534
583
|
return copy_and_convert_datatypes(data.tolist(), use_numpy, use_element_label)
|
|
535
584
|
|
|
536
585
|
elif isinstance(data, TimeSeries):
|
|
537
|
-
return copy_and_convert_datatypes(data.
|
|
586
|
+
return copy_and_convert_datatypes(data.selected_data, use_numpy, use_element_label)
|
|
538
587
|
elif isinstance(data, TimeSeriesData):
|
|
539
588
|
return copy_and_convert_datatypes(data.data, use_numpy, use_element_label)
|
|
589
|
+
elif isinstance(data, (pd.Series, pd.DataFrame)):
|
|
590
|
+
#TODO: This can be improved
|
|
591
|
+
return copy_and_convert_datatypes(data.values, use_numpy, use_element_label)
|
|
540
592
|
|
|
541
593
|
elif isinstance(data, Interface):
|
|
542
594
|
if use_element_label and isinstance(data, Element):
|
|
@@ -584,6 +636,8 @@ def get_compact_representation(data: Any, array_threshold: int = 50, decimals: i
|
|
|
584
636
|
|
|
585
637
|
def normalized_center_of_mass(array: Any) -> float:
|
|
586
638
|
# position in array (0 bis 1 normiert)
|
|
639
|
+
if array.ndim >= 2: # No good way to calculate center of mass for 2D arrays
|
|
640
|
+
return np.nan
|
|
587
641
|
positions = np.linspace(0, 1, len(array)) # weights w_i
|
|
588
642
|
# mass center
|
|
589
643
|
if np.sum(array) == 0:
|
flixopt/utils.py
CHANGED
|
@@ -11,15 +11,6 @@ import xarray as xr
|
|
|
11
11
|
logger = logging.getLogger('flixopt')
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
def is_number(number_alias: Union[int, float, str]):
|
|
15
|
-
"""Returns True is string is a number."""
|
|
16
|
-
try:
|
|
17
|
-
float(number_alias)
|
|
18
|
-
return True
|
|
19
|
-
except ValueError:
|
|
20
|
-
return False
|
|
21
|
-
|
|
22
|
-
|
|
23
14
|
def round_floats(obj, decimals=2):
|
|
24
15
|
if isinstance(obj, dict):
|
|
25
16
|
return {k: round_floats(v, decimals) for k, v in obj.items()}
|
|
@@ -27,6 +18,12 @@ def round_floats(obj, decimals=2):
|
|
|
27
18
|
return [round_floats(v, decimals) for v in obj]
|
|
28
19
|
elif isinstance(obj, float):
|
|
29
20
|
return round(obj, decimals)
|
|
21
|
+
elif isinstance(obj, int):
|
|
22
|
+
return obj
|
|
23
|
+
elif isinstance(obj, np.ndarray):
|
|
24
|
+
return np.round(obj, decimals).tolist()
|
|
25
|
+
elif isinstance(obj, xr.DataArray):
|
|
26
|
+
return obj.round(decimals).values.tolist()
|
|
30
27
|
return obj
|
|
31
28
|
|
|
32
29
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flixopt
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0b0
|
|
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>
|
|
@@ -14,11 +14,12 @@ docs/release-notes/index.md,sha256=6VslOEfF3KQQCbntguRKz7uGWd_W_KIYotP8L1fzAeI,2
|
|
|
14
14
|
docs/release-notes/v2.0.0.md,sha256=eauxvCH3O0B054vhbP0G8GdeF2LM__J57VAGYRFQzBg,4676
|
|
15
15
|
docs/release-notes/v2.0.1.md,sha256=_0oqZjogRv_x6DToWih78uhHu65-J1tat5A1asYxg50,398
|
|
16
16
|
docs/release-notes/v2.1.0.md,sha256=uUnlzG61rI2PYce1SxIySYOnW55e_vnJYJN7l8lcB8A,1325
|
|
17
|
-
docs/release-notes/v2.
|
|
17
|
+
docs/release-notes/v2.2.0.md,sha256=MvIdMzmDA4d-h6UFGPU0dEqWl5PwJC8qPE5NvxxlCJ8,2022
|
|
18
18
|
docs/user-guide/index.md,sha256=fxI_bMjz7czJ5aF_7D7l5rQVpc03WV2EAaBo9y3gB2g,7452
|
|
19
19
|
docs/user-guide/Mathematical Notation/Bus.md,sha256=getjae_-rNTXbotO0euXwYCq2arBoayKsN9KeFb2u60,1612
|
|
20
20
|
"docs/user-guide/Mathematical Notation/Effects, Penalty & Objective.md",sha256=RNqcJzNI1E-U01gaeoKu7m-7gjmtDWvjr2Y5JK9YgTA,5685
|
|
21
21
|
docs/user-guide/Mathematical Notation/Flow.md,sha256=MaBsj5j5dfa1qnUYCKbrNqE2yDZSeJ60_hoq95uhWyg,1094
|
|
22
|
+
docs/user-guide/Mathematical Notation/Investment.md,sha256=NUs8b2Hx1ZNFxSuGqFHx5epk2-qqUQ7I_EG17X5EVPQ,4181
|
|
22
23
|
docs/user-guide/Mathematical Notation/LinearConverter.md,sha256=XNkRgE8-MVNplKT3n1MyIrtgTRkbbwp7-qfapZw2kfU,1322
|
|
23
24
|
docs/user-guide/Mathematical Notation/Piecewise.md,sha256=ia4rkKYrEidWIBsgLMAkt10JH-idmaavJTAMzAlMH_8,1994
|
|
24
25
|
docs/user-guide/Mathematical Notation/Storage.md,sha256=PeNzk77i-81VX8I5r3zen3karF5v3wal9x2_ReUuyho,2199
|
|
@@ -26,34 +27,33 @@ docs/user-guide/Mathematical Notation/index.md,sha256=gkglBsoARhgvppXN9PgdJF33sC
|
|
|
26
27
|
docs/user-guide/Mathematical Notation/others.md,sha256=wOUsfspAoSNTMlTNipeQ8ohoVVX2S-eI3dmlzqqrbR8,47
|
|
27
28
|
flixopt/__init__.py,sha256=F49OK5QLUnMGmsaKQ-G0dXsVuKr9Ow_pjM4KMSNZ918,614
|
|
28
29
|
flixopt/aggregation.py,sha256=UaAYh34C4XhDgiSs4lm31XEMLr4YO5BzLKUAx4NQuyI,17002
|
|
29
|
-
flixopt/calculation.py,sha256=
|
|
30
|
+
flixopt/calculation.py,sha256=u8O11pU-PaY57MybTG63MSa3Rm-fBUTn9OvytZI-3aY,21348
|
|
30
31
|
flixopt/commons.py,sha256=ZNlUN1z-h9OGHPo-s-n5OLlJaoPZKVGcAdRyGKpMk4M,1256
|
|
31
|
-
flixopt/components.py,sha256=
|
|
32
|
+
flixopt/components.py,sha256=lu76ZklsG2fS7xOYYEoutFgj72DLCfqwFpRcBzBZfzs,31377
|
|
32
33
|
flixopt/config.py,sha256=Kt8QYk7hX5qHcQUtfgjM862C6SQr4K2lDvtk_LLER8Y,9085
|
|
33
34
|
flixopt/config.yaml,sha256=imzAnnhcJhIfKNTTXFB5Td7Pvk5ARn5j720k-oGGRug,392
|
|
34
|
-
flixopt/core.py,sha256=
|
|
35
|
-
flixopt/effects.py,sha256=
|
|
36
|
-
flixopt/elements.py,sha256=
|
|
37
|
-
flixopt/features.py,sha256=
|
|
38
|
-
flixopt/flow_system.py,sha256=
|
|
39
|
-
flixopt/interface.py,sha256=
|
|
40
|
-
flixopt/io.py,sha256=
|
|
41
|
-
flixopt/linear_converters.py,sha256=
|
|
42
|
-
flixopt/plotting.py,sha256=
|
|
43
|
-
flixopt/results.py,sha256=
|
|
35
|
+
flixopt/core.py,sha256=IS9IN-WrHTn2U8cbrhkFw3TqLblKNDNzMXZVHatZuks,56359
|
|
36
|
+
flixopt/effects.py,sha256=TELgTCuzu8wYWEmRpQY5r_hBxQIk0pr_hm2Rn-hTpAA,24575
|
|
37
|
+
flixopt/elements.py,sha256=glEvUpHHjZZVUvafRAybNXiqJNlnhWWZ3edgoSfpslc,28630
|
|
38
|
+
flixopt/features.py,sha256=zcLzunoi-LAMUuG6OjJ_4j95zA3b-tptPkgvSN29Als,46725
|
|
39
|
+
flixopt/flow_system.py,sha256=mLEZ0blw5dNLRR8IDBjkQWob_uKeXD-aADQSUy9Vtjw,21090
|
|
40
|
+
flixopt/interface.py,sha256=HKYPO0J3FoEyxa6Wr-BIkEHsGpNwDobXq3zzy1CqoXo,16148
|
|
41
|
+
flixopt/io.py,sha256=S4Ia3lcKykXUEW8qn8pu8JOhqejp001bolCGXO7vleM,12029
|
|
42
|
+
flixopt/linear_converters.py,sha256=xIp0mxw2v5mVzT9ZWYUeJUbh-jYgFiRmku88vOXhtWA,10934
|
|
43
|
+
flixopt/plotting.py,sha256=68O330RnLBNlOcZ-P6WK1YBvRwSoG6x9ELrBcDBOrNA,54879
|
|
44
|
+
flixopt/results.py,sha256=1tD94E2YfOIA8nX5bXR3vnAnBwokO9O0Mlk5zuESF5Q,69189
|
|
44
45
|
flixopt/solvers.py,sha256=k1bSoiXec3asWED70-erXkgtpn2C8KRBfSZj0FLviSM,2436
|
|
45
|
-
flixopt/structure.py,sha256=
|
|
46
|
-
flixopt/utils.py,sha256=
|
|
47
|
-
flixopt-2.
|
|
46
|
+
flixopt/structure.py,sha256=Ufgu8cf1pO4UIww4Lht7I1Iabm6JUxWM-N7gGdNjIdM,28905
|
|
47
|
+
flixopt/utils.py,sha256=xuksGh1dXj8HNhkcjMCVIxlpAA_QSWXePFmkbJYvQwM,1712
|
|
48
|
+
flixopt-2.2.0b0.dist-info/licenses/LICENSE,sha256=HKsZnbrM_3Rvnr_u9cWSG90cBsj5_slaqI_z_qcxnGI,1118
|
|
48
49
|
pics/architecture_flixOpt-pre2.0.0.png,sha256=9RWSA3vys588aadr2437zor-_-xBTQNQ0bAf8xGcu5g,70605
|
|
49
50
|
pics/architecture_flixOpt.png,sha256=KjN1bJwESbkHmTW7UsJ7dZyiKZlTO7Dx20dg8KlR1HU,260219
|
|
50
51
|
pics/flixOpt_plotting.jpg,sha256=zn7ZPAtXm5eRTxtOj86e4-PPhHpCar1jqGh7vMBgQGY,518862
|
|
51
52
|
pics/flixopt-icon.svg,sha256=_1a6bk2pDOVEy233LC1nM6jZ35NdzD8Hd3UqGxW1Xpg,135341
|
|
52
53
|
pics/pics.pptx,sha256=ImWeGGvjtWJ6BGruipsnZYmWtHj5sWdbw1NSFePbkC8,683344
|
|
53
54
|
scripts/gen_ref_pages.py,sha256=AYRtXyz78x5I_Hn0oRtGVbTxgLLj2QNyRX6vWRefPjc,1960
|
|
54
|
-
site/release-notes/_template.txt,sha256=j65E_FDxzimkcMXBrXyF6b2KPm0KAiQlGTxfhQHnN7c,496
|
|
55
55
|
tests/ressources/Zeitreihen2020.csv,sha256=kbsDTKZS0iUsNZAS7m3DohzZI_OHHWe44s3GwLvcTLw,1918412
|
|
56
|
-
flixopt-2.
|
|
57
|
-
flixopt-2.
|
|
58
|
-
flixopt-2.
|
|
59
|
-
flixopt-2.
|
|
56
|
+
flixopt-2.2.0b0.dist-info/METADATA,sha256=0O2Ass8s06oafXxxkjUbHtWdfmeUUjCmUzjzcBE3uZI,7157
|
|
57
|
+
flixopt-2.2.0b0.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
|
|
58
|
+
flixopt-2.2.0b0.dist-info/top_level.txt,sha256=DEuo4R1z7GmEp5R3pjbQEJbaPRjKHFvNX2ceiBnVOL0,32
|
|
59
|
+
flixopt-2.2.0b0.dist-info/RECORD,,
|
docs/release-notes/v2.1.1.md
DELETED
site/release-notes/_template.txt
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# Release v{version}
|
|
2
|
-
|
|
3
|
-
**Release Date:** YYYY-MM-DD
|
|
4
|
-
|
|
5
|
-
## What's New
|
|
6
|
-
|
|
7
|
-
* Feature 1 - Description
|
|
8
|
-
* Feature 2 - Description
|
|
9
|
-
|
|
10
|
-
## Improvements
|
|
11
|
-
|
|
12
|
-
* Improvement 1 - Description
|
|
13
|
-
* Improvement 2 - Description
|
|
14
|
-
|
|
15
|
-
## Bug Fixes
|
|
16
|
-
|
|
17
|
-
* Fixed issue with X
|
|
18
|
-
* Resolved problem with Y
|
|
19
|
-
|
|
20
|
-
## Breaking Changes
|
|
21
|
-
|
|
22
|
-
* Change 1 - Migration instructions
|
|
23
|
-
* Change 2 - Migration instructions
|
|
24
|
-
|
|
25
|
-
## Deprecations
|
|
26
|
-
|
|
27
|
-
* Feature X will be removed in v{next_version}
|
|
28
|
-
|
|
29
|
-
## Dependencies
|
|
30
|
-
|
|
31
|
-
* Added dependency X v1.2.3
|
|
32
|
-
* Updated dependency Y to v2.0.0
|
|
File without changes
|