epyt-flow 0.8.1__py3-none-any.whl → 0.10.0__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.
- epyt_flow/VERSION +1 -1
- epyt_flow/__init__.py +1 -0
- epyt_flow/data/benchmarks/batadal.py +1 -1
- epyt_flow/data/benchmarks/battledim.py +4 -3
- epyt_flow/data/benchmarks/gecco_water_quality.py +4 -4
- epyt_flow/data/benchmarks/leakdb.py +7 -7
- epyt_flow/data/benchmarks/water_usage.py +2 -2
- epyt_flow/data/networks.py +1 -1
- epyt_flow/gym/control_gyms.py +2 -2
- epyt_flow/gym/scenario_control_env.py +9 -1
- epyt_flow/metrics.py +28 -28
- epyt_flow/models/sensor_interpolation_detector.py +3 -3
- epyt_flow/rest_api/base_handler.py +4 -4
- epyt_flow/rest_api/scada_data/data_handlers.py +11 -11
- epyt_flow/rest_api/scada_data/export_handlers.py +2 -2
- epyt_flow/rest_api/scada_data/handlers.py +9 -9
- epyt_flow/rest_api/scenario/event_handlers.py +6 -6
- epyt_flow/rest_api/scenario/handlers.py +15 -15
- epyt_flow/rest_api/scenario/simulation_handlers.py +7 -7
- epyt_flow/rest_api/scenario/uncertainty_handlers.py +6 -6
- epyt_flow/serialization.py +8 -2
- epyt_flow/simulation/events/actuator_events.py +1 -1
- epyt_flow/simulation/events/leakages.py +1 -1
- epyt_flow/simulation/events/quality_events.py +16 -5
- epyt_flow/simulation/events/sensor_reading_attack.py +17 -4
- epyt_flow/simulation/events/sensor_reading_event.py +21 -6
- epyt_flow/simulation/events/system_event.py +1 -1
- epyt_flow/simulation/parallel_simulation.py +1 -1
- epyt_flow/simulation/scada/__init__.py +3 -1
- epyt_flow/simulation/scada/advanced_control.py +8 -4
- epyt_flow/simulation/scada/complex_control.py +625 -0
- epyt_flow/simulation/scada/custom_control.py +134 -0
- epyt_flow/simulation/scada/scada_data.py +133 -130
- epyt_flow/simulation/scada/scada_data_export.py +1 -1
- epyt_flow/simulation/scada/simple_control.py +317 -0
- epyt_flow/simulation/scenario_config.py +124 -24
- epyt_flow/simulation/scenario_simulator.py +514 -49
- epyt_flow/simulation/scenario_visualizer.py +9 -9
- epyt_flow/simulation/sensor_config.py +38 -28
- epyt_flow/topology.py +2 -2
- epyt_flow/uncertainty/model_uncertainty.py +624 -147
- epyt_flow/uncertainty/sensor_noise.py +94 -19
- epyt_flow/uncertainty/uncertainties.py +4 -4
- epyt_flow/uncertainty/utils.py +7 -7
- epyt_flow/utils.py +9 -8
- {epyt_flow-0.8.1.dist-info → epyt_flow-0.10.0.dist-info}/LICENSE +1 -1
- {epyt_flow-0.8.1.dist-info → epyt_flow-0.10.0.dist-info}/METADATA +7 -6
- {epyt_flow-0.8.1.dist-info → epyt_flow-0.10.0.dist-info}/RECORD +50 -47
- {epyt_flow-0.8.1.dist-info → epyt_flow-0.10.0.dist-info}/WHEEL +1 -1
- {epyt_flow-0.8.1.dist-info → epyt_flow-0.10.0.dist-info}/top_level.txt +0 -0
|
@@ -4,6 +4,7 @@ Module provides a class for implementing model uncertainty.
|
|
|
4
4
|
from copy import deepcopy
|
|
5
5
|
import warnings
|
|
6
6
|
import epyt
|
|
7
|
+
from epyt.epanet import ToolkitConstants
|
|
7
8
|
import numpy as np
|
|
8
9
|
|
|
9
10
|
from ..serialization import serializable, JsonSerializable, MODEL_UNCERTAINTY_ID
|
|
@@ -18,36 +19,99 @@ class ModelUncertainty(JsonSerializable):
|
|
|
18
19
|
|
|
19
20
|
Parameters
|
|
20
21
|
----------
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
global_pipe_length_uncertainty : :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`, optional
|
|
23
|
+
Global uncertainty of pipe lengths. None, in the case of no uncertainty.
|
|
23
24
|
|
|
24
25
|
The default is None.
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
global_pipe_roughness_uncertainty : :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`, optional
|
|
27
|
+
Global uncertainty of pipe roughness coefficients. None, in the case of no uncertainty.
|
|
27
28
|
|
|
28
29
|
The default is None.
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
global_pipe_diameter_uncertainty : :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`, optional
|
|
31
|
+
Global uncertainty of pipe diameters. None, in the case of no uncertainty.
|
|
31
32
|
|
|
32
33
|
The default is None.
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
global_base_demand_uncertainty : :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`, optional
|
|
35
|
+
Global uncertainty of base demands. None, in the case of no uncertainty.
|
|
35
36
|
|
|
36
37
|
The default is None.
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
global_demand_pattern_uncertainty : :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`, optional
|
|
39
|
+
Global uncertainty of demand patterns. None, in the case of no uncertainty.
|
|
39
40
|
|
|
40
41
|
The default is None.
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
global_elevation_uncertainty : :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`, optional
|
|
43
|
+
Global uncertainty of elevations. None, in the case of no uncertainty.
|
|
43
44
|
|
|
44
45
|
The default is None.
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
global_constants_uncertainty : :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`, optional
|
|
47
|
+
Global uncertainty of MSX constants. None, in the case of no uncertainty.
|
|
47
48
|
|
|
48
49
|
The default is None.
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
global_parameters_uncertainty : :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`, optional
|
|
51
|
+
Global uncertainty of MSX parameters. None, in the case of no uncertaint.
|
|
52
|
+
|
|
53
|
+
The default is None.
|
|
54
|
+
local_pipe_length_uncertainty : dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`], optional
|
|
55
|
+
Local uncertainty of pipe lengths -- i.e. a dictionary of pipe IDs and uncertainties.
|
|
56
|
+
|
|
57
|
+
None, in the case of no uncertainty.
|
|
58
|
+
|
|
59
|
+
The default is None.
|
|
60
|
+
local_pipe_roughness_uncertainty : dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`], optional
|
|
61
|
+
Local uncertainty of pipe roughness coefficients -- i.e. a dictionary of pipe IDs and uncertainties.
|
|
62
|
+
|
|
63
|
+
None, in the case of no uncertainty.
|
|
64
|
+
|
|
65
|
+
The default is None.
|
|
66
|
+
local_pipe_diameter_uncertainty : dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`], optional
|
|
67
|
+
Local uncertainty of pipe diameters -- i.e. a dictionary of pipe IDs and uncertainties.
|
|
68
|
+
|
|
69
|
+
None, in the case of no uncertainty.
|
|
70
|
+
|
|
71
|
+
The default is None.
|
|
72
|
+
local_base_demand_uncertainty : dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`], optional
|
|
73
|
+
Local uncertainty of base demands -- i.e. a dictionary of node IDs and uncertainties.
|
|
74
|
+
|
|
75
|
+
None, in the case of no uncertainty.
|
|
76
|
+
|
|
77
|
+
The default is None.
|
|
78
|
+
local_demand_pattern_uncertainty : dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`], optional
|
|
79
|
+
Local uncertainty of demand patterns --
|
|
80
|
+
i.e. a dictionary of demand pattern IDs and uncertainties.
|
|
81
|
+
|
|
82
|
+
None, in the case of no uncertainty.
|
|
83
|
+
|
|
84
|
+
The default is None.
|
|
85
|
+
local_elevation_uncertainty : dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`], optional
|
|
86
|
+
Local uncertainty of elevations -- i.e. a dictionary of node IDs and uncertainties.
|
|
87
|
+
|
|
88
|
+
None, in the case of no uncertainty.
|
|
89
|
+
|
|
90
|
+
The default is None.
|
|
91
|
+
local_constants_uncertainty : dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`], optional
|
|
92
|
+
Local uncertainty of MSX constants -- i.e. a dictionary of constant IDs and uncertainties.
|
|
93
|
+
|
|
94
|
+
None, in the case of no uncertainty.
|
|
95
|
+
|
|
96
|
+
The default is None.
|
|
97
|
+
local_parameters_uncertainty : dict[tuple[str, int, str] :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`], optional
|
|
98
|
+
Local uncertainty of MSX parameters -- i.e. a dictionary of
|
|
99
|
+
(parameter ID, item type, item ID) and uncertainties.
|
|
100
|
+
|
|
101
|
+
None, in the case of no uncertainty.
|
|
102
|
+
|
|
103
|
+
The default is None.
|
|
104
|
+
local_patterns_uncertainty : dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`], optional
|
|
105
|
+
Local uncertainty of EPANET patterns -- i.e. a dictionary of pattern IDs and uncertainties.
|
|
106
|
+
|
|
107
|
+
None, in the case of no uncertainty.
|
|
108
|
+
|
|
109
|
+
The default is None.
|
|
110
|
+
local_msx_patterns_uncertainty : dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`], optional
|
|
111
|
+
Local uncertainty of EPANET-MSX patterns -- i.e. a dictionary of MSX pattern IDs
|
|
112
|
+
and uncertainties.
|
|
113
|
+
|
|
114
|
+
None, in the case of no uncertainty.
|
|
51
115
|
|
|
52
116
|
The default is None.
|
|
53
117
|
"""
|
|
@@ -59,188 +123,504 @@ class ModelUncertainty(JsonSerializable):
|
|
|
59
123
|
elevation_uncertainty: Uncertainty = None,
|
|
60
124
|
constants_uncertainty: Uncertainty = None,
|
|
61
125
|
parameters_uncertainty: Uncertainty = None,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
126
|
+
global_pipe_length_uncertainty: Uncertainty = None,
|
|
127
|
+
global_pipe_roughness_uncertainty: Uncertainty = None,
|
|
128
|
+
global_pipe_diameter_uncertainty: Uncertainty = None,
|
|
129
|
+
global_base_demand_uncertainty: Uncertainty = None,
|
|
130
|
+
global_demand_pattern_uncertainty: Uncertainty = None,
|
|
131
|
+
global_elevation_uncertainty: Uncertainty = None,
|
|
132
|
+
global_constants_uncertainty: Uncertainty = None,
|
|
133
|
+
global_parameters_uncertainty: Uncertainty = None,
|
|
134
|
+
local_pipe_length_uncertainty: dict[str, Uncertainty] = None,
|
|
135
|
+
local_pipe_roughness_uncertainty: dict[str, Uncertainty] = None,
|
|
136
|
+
local_pipe_diameter_uncertainty: dict[str, Uncertainty] = None,
|
|
137
|
+
local_base_demand_uncertainty: dict[str, Uncertainty] = None,
|
|
138
|
+
local_demand_pattern_uncertainty: dict[str, Uncertainty] = None,
|
|
139
|
+
local_elevation_uncertainty: dict[str, Uncertainty] = None,
|
|
140
|
+
local_constants_uncertainty: dict[str, Uncertainty] = None,
|
|
141
|
+
local_parameters_uncertainty: dict[str, int, Uncertainty] = None,
|
|
142
|
+
local_patterns_uncertainty: dict[str, Uncertainty] = None,
|
|
143
|
+
local_msx_patterns_uncertainty: dict[str, Uncertainty] = None,
|
|
144
|
+
**kwds):
|
|
68
145
|
if pipe_length_uncertainty is not None:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
f"'{type(pipe_length_uncertainty)}'")
|
|
146
|
+
global_pipe_diameter_uncertainty = pipe_length_uncertainty
|
|
147
|
+
warnings.warn("'pipe_length_uncertainty' is deprecated and " +
|
|
148
|
+
"will be removed in future releases")
|
|
73
149
|
if pipe_roughness_uncertainty is not None:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
f"'{type(pipe_roughness_uncertainty)}'")
|
|
150
|
+
global_pipe_roughness_uncertainty = pipe_roughness_uncertainty
|
|
151
|
+
warnings.warn("'pipe_roughness_uncertainty' is deprecated and " +
|
|
152
|
+
"will be removed in future releases")
|
|
78
153
|
if pipe_diameter_uncertainty is not None:
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
f"'{type(pipe_diameter_uncertainty)}'")
|
|
154
|
+
global_pipe_diameter_uncertainty = pipe_diameter_uncertainty
|
|
155
|
+
warnings.warn("'pipe_diameter_uncertainty' is deprecated and " +
|
|
156
|
+
"will be removed in future releases")
|
|
83
157
|
if base_demand_uncertainty is not None:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
f"'{type(base_demand_uncertainty)}'")
|
|
158
|
+
global_base_demand_uncertainty = base_demand_uncertainty
|
|
159
|
+
warnings.warn("'base_demand_uncertainty' is deprecated and " +
|
|
160
|
+
"will be removed in future releases")
|
|
88
161
|
if demand_pattern_uncertainty is not None:
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
f"'{type(demand_pattern_uncertainty)}'")
|
|
162
|
+
global_demand_pattern_uncertainty = demand_pattern_uncertainty
|
|
163
|
+
warnings.warn("'demand_pattern_uncertainty' is deprecated and " +
|
|
164
|
+
"will be removed in future releases")
|
|
93
165
|
if elevation_uncertainty is not None:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
f"'{type(elevation_uncertainty)}'")
|
|
166
|
+
global_elevation_uncertainty = elevation_uncertainty
|
|
167
|
+
warnings.warn("'elevation_uncertainty' is deprecated and " +
|
|
168
|
+
"will be removed in future releases")
|
|
98
169
|
if constants_uncertainty is not None:
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
f"'{type(constants_uncertainty)}'")
|
|
170
|
+
global_constants_uncertainty = constants_uncertainty
|
|
171
|
+
warnings.warn("'constants_uncertainty' is deprecated and " +
|
|
172
|
+
"will be removed in future releases")
|
|
103
173
|
if parameters_uncertainty is not None:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
f"'{type(parameters_uncertainty)}'")
|
|
174
|
+
global_parameters_uncertainty = parameters_uncertainty
|
|
175
|
+
warnings.warn("'parameters_uncertainty' is deprecated and " +
|
|
176
|
+
"will be removed in future releases")
|
|
108
177
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
178
|
+
if global_pipe_length_uncertainty is not None:
|
|
179
|
+
if not isinstance(global_pipe_length_uncertainty, Uncertainty):
|
|
180
|
+
raise TypeError("'global_pipe_length_uncertainty' must be an instance of " +
|
|
181
|
+
"'epyt_flow.uncertainty.Uncertainty' but not of " +
|
|
182
|
+
f"'{type(global_pipe_length_uncertainty)}'")
|
|
183
|
+
if global_pipe_roughness_uncertainty is not None:
|
|
184
|
+
if not isinstance(global_pipe_roughness_uncertainty, Uncertainty):
|
|
185
|
+
raise TypeError("'global_pipe_roughness_uncertainty' must be an instance of " +
|
|
186
|
+
"'epyt_flow.uncertainty.Uncertainty' but not of " +
|
|
187
|
+
f"'{type(global_pipe_roughness_uncertainty)}'")
|
|
188
|
+
if global_pipe_diameter_uncertainty is not None:
|
|
189
|
+
if not isinstance(global_pipe_diameter_uncertainty, Uncertainty):
|
|
190
|
+
raise TypeError("'global_pipe_diameter_uncertainty' must be an instance of " +
|
|
191
|
+
"'epyt_flow.uncertainty.Uncertainty' but not of " +
|
|
192
|
+
f"'{type(global_pipe_diameter_uncertainty)}'")
|
|
193
|
+
if global_base_demand_uncertainty is not None:
|
|
194
|
+
if not isinstance(global_base_demand_uncertainty, Uncertainty):
|
|
195
|
+
raise TypeError("'global_base_demand_uncertainty' must be an instance of " +
|
|
196
|
+
"'epyt_flow.uncertainty.Uncertainty' but not of " +
|
|
197
|
+
f"'{type(global_base_demand_uncertainty)}'")
|
|
198
|
+
if global_demand_pattern_uncertainty is not None:
|
|
199
|
+
if not isinstance(global_demand_pattern_uncertainty, Uncertainty):
|
|
200
|
+
raise TypeError("'global_demand_pattern_uncertainty' must be an instance of " +
|
|
201
|
+
"'epyt_flow.uncertainty.Uncertainty' but not of " +
|
|
202
|
+
f"'{type(global_demand_pattern_uncertainty)}'")
|
|
203
|
+
if global_elevation_uncertainty is not None:
|
|
204
|
+
if not isinstance(global_elevation_uncertainty, Uncertainty):
|
|
205
|
+
raise TypeError("'global_elevation_uncertainty' must be an instance of " +
|
|
206
|
+
"'epyt_flow.uncertainty.Uncertainty' but not of " +
|
|
207
|
+
f"'{type(global_elevation_uncertainty)}'")
|
|
208
|
+
if global_constants_uncertainty is not None:
|
|
209
|
+
if not isinstance(global_constants_uncertainty, Uncertainty):
|
|
210
|
+
raise TypeError("'global_constants_uncertainty' must be an instance of " +
|
|
211
|
+
"'epyt_flow.uncertainty.Uncertainty' but not of " +
|
|
212
|
+
f"'{type(global_constants_uncertainty)}'")
|
|
213
|
+
if global_parameters_uncertainty is not None:
|
|
214
|
+
if not isinstance(global_parameters_uncertainty, Uncertainty):
|
|
215
|
+
raise TypeError("'global_parameters_uncertainty' must be an instance of " +
|
|
216
|
+
"'epyt_flow.uncertainty.Uncertainty' but not of " +
|
|
217
|
+
f"'{type(global_parameters_uncertainty)}'")
|
|
218
|
+
|
|
219
|
+
if local_pipe_length_uncertainty is not None:
|
|
220
|
+
if not isinstance(local_pipe_length_uncertainty, dict):
|
|
221
|
+
raise TypeError("'local_pipe_length_uncertainty' must be an instance of " +
|
|
222
|
+
"'dict[str, epyt_flow.uncertainty.Uncertainty]' but not of " +
|
|
223
|
+
f"'{type(local_pipe_length_uncertainty)}'")
|
|
224
|
+
if any(not isinstance(key, str) or not isinstance(val, Uncertainty)
|
|
225
|
+
for key, val in local_pipe_length_uncertainty.items()):
|
|
226
|
+
raise TypeError("'local_pipe_length_uncertainty': " +
|
|
227
|
+
"All keys must be instances of 'str' and all values must be " +
|
|
228
|
+
"instances of 'epyt_flow.uncertainty.Uncertainty'")
|
|
229
|
+
if local_pipe_roughness_uncertainty is not None:
|
|
230
|
+
if not isinstance(local_pipe_roughness_uncertainty, dict):
|
|
231
|
+
raise TypeError("'local_pipe_roughness_uncertainty' must be an instance of " +
|
|
232
|
+
"'dict[str, epyt_flow.uncertainty.Uncertainty]' but not of " +
|
|
233
|
+
f"'{type(local_pipe_roughness_uncertainty)}'")
|
|
234
|
+
if any(not isinstance(key, str) or not isinstance(val, Uncertainty)
|
|
235
|
+
for key, val in local_pipe_roughness_uncertainty.items()):
|
|
236
|
+
raise TypeError("'local_pipe_roughness_uncertainty': " +
|
|
237
|
+
"All keys must be instances of 'str' and all values must be " +
|
|
238
|
+
"instances of 'epyt_flow.uncertainty.Uncertainty'")
|
|
239
|
+
if local_pipe_diameter_uncertainty is not None:
|
|
240
|
+
if not isinstance(local_pipe_diameter_uncertainty, dict):
|
|
241
|
+
raise TypeError("'local_pipe_diameter_uncertainty' must be an instance of " +
|
|
242
|
+
"'dict[str, epyt_flow.uncertainty.Uncertainty]' but not of " +
|
|
243
|
+
f"'{type(local_pipe_diameter_uncertainty)}'")
|
|
244
|
+
if any(not isinstance(key, str) or not isinstance(val, Uncertainty)
|
|
245
|
+
for key, val in local_pipe_diameter_uncertainty.items()):
|
|
246
|
+
raise TypeError("'local_pipe_diameter_uncertainty': " +
|
|
247
|
+
"All keys must be instances of 'str' and all values must be " +
|
|
248
|
+
"instances of 'epyt_flow.uncertainty.Uncertainty'")
|
|
249
|
+
if local_base_demand_uncertainty is not None:
|
|
250
|
+
if not isinstance(local_base_demand_uncertainty, dict):
|
|
251
|
+
raise TypeError("'local_base_demand_uncertainty' must be an instance of " +
|
|
252
|
+
"'dict[str, epyt_flow.uncertainty.Uncertainty]' but not of " +
|
|
253
|
+
f"'{type(local_base_demand_uncertainty)}'")
|
|
254
|
+
if any(not isinstance(key, str) or not isinstance(val, Uncertainty)
|
|
255
|
+
for key, val in local_base_demand_uncertainty.items()):
|
|
256
|
+
raise TypeError("'local_base_demand_uncertainty': " +
|
|
257
|
+
"All keys must be instances of 'str' and all values must be " +
|
|
258
|
+
"instances of 'epyt_flow.uncertainty.Uncertainty'")
|
|
259
|
+
if local_demand_pattern_uncertainty is not None:
|
|
260
|
+
if not isinstance(local_demand_pattern_uncertainty, dict):
|
|
261
|
+
raise TypeError("'local_demand_pattern_uncertainty' must be an instance of " +
|
|
262
|
+
"'dict[str, epyt_flow.uncertainty.Uncertainty]' but not of " +
|
|
263
|
+
f"'{type(local_demand_pattern_uncertainty)}'")
|
|
264
|
+
if any(not isinstance(key, str) or not isinstance(val, Uncertainty)
|
|
265
|
+
for key, val in local_demand_pattern_uncertainty.items()):
|
|
266
|
+
raise TypeError("'local_demand_pattern_uncertainty': " +
|
|
267
|
+
"All keys must be instances of 'str' and all values must be " +
|
|
268
|
+
"instances of 'epyt_flow.uncertainty.Uncertainty'")
|
|
269
|
+
if local_elevation_uncertainty is not None:
|
|
270
|
+
if not isinstance(local_elevation_uncertainty, dict):
|
|
271
|
+
raise TypeError("'local_elevation_uncertainty' must be an instance of " +
|
|
272
|
+
"'dict[str, epyt_flow.uncertainty.Uncertainty]' but not of " +
|
|
273
|
+
f"'{type(local_elevation_uncertainty)}'")
|
|
274
|
+
if any(not isinstance(key, str) or not isinstance(val, Uncertainty)
|
|
275
|
+
for key, val in local_elevation_uncertainty.items()):
|
|
276
|
+
raise TypeError("'local_elevation_uncertainty': " +
|
|
277
|
+
"All keys must be instances of 'str' and all values must be " +
|
|
278
|
+
"instances of 'epyt_flow.uncertainty.Uncertainty'")
|
|
279
|
+
if local_constants_uncertainty is not None:
|
|
280
|
+
if not isinstance(local_constants_uncertainty, dict):
|
|
281
|
+
raise TypeError("'local_constants_uncertainty' must be an instance of " +
|
|
282
|
+
"'dict[str, epyt_flow.uncertainty.Uncertainty]' but not of " +
|
|
283
|
+
f"'{type(local_constants_uncertainty)}'")
|
|
284
|
+
if any(not isinstance(key, str) or not isinstance(val, Uncertainty)
|
|
285
|
+
for key, val in local_constants_uncertainty.items()):
|
|
286
|
+
raise TypeError("'local_constants_uncertainty': " +
|
|
287
|
+
"All keys must be instances of 'str' and all values must be " +
|
|
288
|
+
"instances of 'epyt_flow.uncertainty.Uncertainty'")
|
|
289
|
+
if local_parameters_uncertainty is not None:
|
|
290
|
+
if not isinstance(local_parameters_uncertainty, dict):
|
|
291
|
+
raise TypeError("'local_parameters_uncertainty' must be an instance of " +
|
|
292
|
+
"'dict[str, epyt_flow.uncertainty.Uncertainty]' but not of " +
|
|
293
|
+
f"'{type(local_parameters_uncertainty)}'")
|
|
294
|
+
if any(not isinstance(key, tuple) or not isinstance(key[0], str) or
|
|
295
|
+
not isinstance(key[1], int) or not isinstance(key[2], str) or
|
|
296
|
+
not isinstance(local_parameters_uncertainty[key], Uncertainty)
|
|
297
|
+
for key in local_parameters_uncertainty.keys()):
|
|
298
|
+
raise TypeError("'local_parameters_uncertainty': " +
|
|
299
|
+
"All keys must be instances of 'tuple[str, int, str]' and all " +
|
|
300
|
+
"values must be instances of 'epyt_flow.uncertainty.Uncertainty'")
|
|
301
|
+
if local_patterns_uncertainty is not None:
|
|
302
|
+
if not isinstance(local_patterns_uncertainty, dict):
|
|
303
|
+
raise TypeError("'local_patterns_uncertainty' must be an instance of " +
|
|
304
|
+
"'dict[str, epyt_flow.uncertainty.Uncertainty]' but not of " +
|
|
305
|
+
f"'{type(local_patterns_uncertainty)}'")
|
|
306
|
+
if any(not isinstance(key, str) or not isinstance(val, Uncertainty)
|
|
307
|
+
for key, val in local_patterns_uncertainty.items()):
|
|
308
|
+
raise TypeError("'local_patterns_uncertainty': " +
|
|
309
|
+
"All keys must be instances of 'str' and all values must be " +
|
|
310
|
+
"instances of 'epyt_flow.uncertainty.Uncertainty'")
|
|
311
|
+
if local_msx_patterns_uncertainty is not None:
|
|
312
|
+
if not isinstance(local_msx_patterns_uncertainty, dict):
|
|
313
|
+
raise TypeError("'local_msx_patterns_uncertainty' must be an instance of " +
|
|
314
|
+
"'dict[str, epyt_flow.uncertainty.Uncertainty]' but not of " +
|
|
315
|
+
f"'{type(local_msx_patterns_uncertainty)}'")
|
|
316
|
+
if any(not isinstance(key, str) or not isinstance(val, Uncertainty)
|
|
317
|
+
for key, val in local_msx_patterns_uncertainty.items()):
|
|
318
|
+
raise TypeError("'local_msx_patterns_uncertainty': " +
|
|
319
|
+
"All keys must be instances of 'str' and all values must be " +
|
|
320
|
+
"instances of 'epyt_flow.uncertainty.Uncertainty'")
|
|
321
|
+
|
|
322
|
+
self.__global_pipe_length = global_pipe_length_uncertainty
|
|
323
|
+
self.__global_pipe_roughness = global_pipe_roughness_uncertainty
|
|
324
|
+
self.__global_pipe_diameter = global_pipe_diameter_uncertainty
|
|
325
|
+
self.__global_base_demand = global_base_demand_uncertainty
|
|
326
|
+
self.__global_demand_pattern = global_demand_pattern_uncertainty
|
|
327
|
+
self.__global_elevation = global_elevation_uncertainty
|
|
328
|
+
self.__global_constants = global_constants_uncertainty
|
|
329
|
+
self.__global_parameters = global_parameters_uncertainty
|
|
330
|
+
self.__local_pipe_length = local_pipe_length_uncertainty
|
|
331
|
+
self.__local_pipe_roughness = local_pipe_roughness_uncertainty
|
|
332
|
+
self.__local_pipe_diameter = local_pipe_diameter_uncertainty
|
|
333
|
+
self.__local_base_demand = local_base_demand_uncertainty
|
|
334
|
+
self.__local_demand_pattern = local_demand_pattern_uncertainty
|
|
335
|
+
self.__local_elevation = local_elevation_uncertainty
|
|
336
|
+
self.__local_constants = local_constants_uncertainty
|
|
337
|
+
self.__local_parameters = local_parameters_uncertainty
|
|
338
|
+
self.__local_patterns = local_patterns_uncertainty
|
|
339
|
+
self.__local_msx_patterns = local_msx_patterns_uncertainty
|
|
117
340
|
|
|
118
341
|
super().__init__(**kwds)
|
|
119
342
|
|
|
120
343
|
@property
|
|
121
|
-
def
|
|
344
|
+
def global_pipe_length(self) -> Uncertainty:
|
|
122
345
|
"""
|
|
123
|
-
|
|
346
|
+
Returns the global pipe length uncertainty.
|
|
124
347
|
|
|
125
348
|
Returns
|
|
126
349
|
-------
|
|
127
350
|
:class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`
|
|
128
|
-
|
|
351
|
+
Global pipe length uncertainty.
|
|
129
352
|
"""
|
|
130
|
-
return deepcopy(self.
|
|
353
|
+
return deepcopy(self.__global_pipe_length)
|
|
131
354
|
|
|
132
355
|
@property
|
|
133
|
-
def
|
|
356
|
+
def global_pipe_roughness(self) -> Uncertainty:
|
|
134
357
|
"""
|
|
135
|
-
|
|
358
|
+
Returns the global pipe roughness uncertainty.
|
|
136
359
|
|
|
137
360
|
Returns
|
|
138
361
|
-------
|
|
139
362
|
:class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`
|
|
140
|
-
|
|
363
|
+
Global pipe roughness uncertainty.
|
|
141
364
|
"""
|
|
142
|
-
return deepcopy(self.
|
|
365
|
+
return deepcopy(self.__global_pipe_roughness)
|
|
143
366
|
|
|
144
367
|
@property
|
|
145
|
-
def
|
|
368
|
+
def global_pipe_diameter(self) -> Uncertainty:
|
|
146
369
|
"""
|
|
147
|
-
|
|
370
|
+
Returns the global pipe diameter uncertainty.
|
|
148
371
|
|
|
149
372
|
Returns
|
|
150
373
|
-------
|
|
151
374
|
:class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`
|
|
152
|
-
|
|
375
|
+
Global pipe diameter uncertainty.
|
|
153
376
|
"""
|
|
154
|
-
return deepcopy(self.
|
|
377
|
+
return deepcopy(self.__global_pipe_diameter)
|
|
155
378
|
|
|
156
379
|
@property
|
|
157
|
-
def
|
|
380
|
+
def global_base_demand(self) -> Uncertainty:
|
|
158
381
|
"""
|
|
159
|
-
|
|
382
|
+
Returns the global base demand uncertainty.
|
|
160
383
|
|
|
161
384
|
Returns
|
|
162
385
|
-------
|
|
163
386
|
:class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`
|
|
164
|
-
|
|
387
|
+
Global base demand uncertainty.
|
|
165
388
|
"""
|
|
166
|
-
return deepcopy(self.
|
|
389
|
+
return deepcopy(self.__global_base_demand)
|
|
167
390
|
|
|
168
391
|
@property
|
|
169
|
-
def
|
|
392
|
+
def global_demand_pattern(self) -> Uncertainty:
|
|
170
393
|
"""
|
|
171
|
-
|
|
394
|
+
Returns the global demand pattern uncertainty.
|
|
172
395
|
|
|
173
396
|
Returns
|
|
174
397
|
-------
|
|
175
398
|
:class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`
|
|
176
|
-
|
|
399
|
+
Global demand pattern uncertainty.
|
|
177
400
|
"""
|
|
178
|
-
return deepcopy(self.
|
|
401
|
+
return deepcopy(self.__global_demand_pattern)
|
|
179
402
|
|
|
180
403
|
@property
|
|
181
|
-
def
|
|
404
|
+
def global_elevation(self) -> Uncertainty:
|
|
182
405
|
"""
|
|
183
|
-
|
|
406
|
+
Returns the global node elevation uncertainty.
|
|
184
407
|
|
|
185
408
|
Returns
|
|
186
409
|
-------
|
|
187
410
|
:class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`
|
|
188
|
-
|
|
411
|
+
Global node elevation uncertainty.
|
|
189
412
|
"""
|
|
190
|
-
return deepcopy(self.
|
|
413
|
+
return deepcopy(self.__global_elevation)
|
|
191
414
|
|
|
192
415
|
@property
|
|
193
|
-
def
|
|
416
|
+
def global_constants(self) -> Uncertainty:
|
|
194
417
|
"""
|
|
195
|
-
|
|
418
|
+
Returns the global MSX constant uncertainty.
|
|
196
419
|
|
|
197
420
|
Returns
|
|
198
421
|
-------
|
|
199
422
|
:class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`
|
|
200
|
-
MSX constant uncertainty.
|
|
423
|
+
Global MSX constant uncertainty.
|
|
201
424
|
"""
|
|
202
|
-
return deepcopy(self.
|
|
425
|
+
return deepcopy(self.__global_constants)
|
|
203
426
|
|
|
204
427
|
@property
|
|
205
|
-
def
|
|
428
|
+
def global_parameters(self) -> Uncertainty:
|
|
206
429
|
"""
|
|
207
|
-
|
|
430
|
+
Returns the global MSX parameter uncertainty.
|
|
208
431
|
|
|
209
432
|
Returns
|
|
210
433
|
-------
|
|
211
434
|
:class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`
|
|
212
|
-
MSX parameter uncertainty.
|
|
435
|
+
Global MSX parameter uncertainty.
|
|
436
|
+
"""
|
|
437
|
+
return deepcopy(self.__global_parameters)
|
|
438
|
+
|
|
439
|
+
@property
|
|
440
|
+
def local_pipe_length(self) -> dict[str, Uncertainty]:
|
|
441
|
+
"""
|
|
442
|
+
Returns the local pipe length uncertainty.
|
|
443
|
+
|
|
444
|
+
Returns
|
|
445
|
+
-------
|
|
446
|
+
dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`]
|
|
447
|
+
Local pipe length uncertainty.
|
|
448
|
+
"""
|
|
449
|
+
return deepcopy(self.__local_pipe_length)
|
|
450
|
+
|
|
451
|
+
@property
|
|
452
|
+
def local_pipe_roughness(self) -> dict[str, Uncertainty]:
|
|
453
|
+
"""
|
|
454
|
+
Returns the local pipe roughness uncertainty.
|
|
455
|
+
|
|
456
|
+
Returns
|
|
457
|
+
-------
|
|
458
|
+
dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`]
|
|
459
|
+
Local pipe roughness uncertainty.
|
|
460
|
+
"""
|
|
461
|
+
return deepcopy(self.__local_pipe_roughness)
|
|
462
|
+
|
|
463
|
+
@property
|
|
464
|
+
def local_pipe_diameter(self) -> dict[str, Uncertainty]:
|
|
465
|
+
"""
|
|
466
|
+
Returns the local pipe diameter uncertainty.
|
|
467
|
+
|
|
468
|
+
Returns
|
|
469
|
+
-------
|
|
470
|
+
dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`]
|
|
471
|
+
Local pipe diameter uncertainty.
|
|
472
|
+
"""
|
|
473
|
+
return deepcopy(self.__local_pipe_diameter)
|
|
474
|
+
|
|
475
|
+
@property
|
|
476
|
+
def local_base_demand(self) -> dict[str, Uncertainty]:
|
|
477
|
+
"""
|
|
478
|
+
Returns the local base demand uncertainty.
|
|
479
|
+
|
|
480
|
+
Returns
|
|
481
|
+
-------
|
|
482
|
+
dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`]
|
|
483
|
+
Local base demand uncertainty.
|
|
484
|
+
"""
|
|
485
|
+
return deepcopy(self.__local_base_demand)
|
|
486
|
+
|
|
487
|
+
@property
|
|
488
|
+
def local_demand_pattern(self) -> dict[str, Uncertainty]:
|
|
489
|
+
"""
|
|
490
|
+
Returns the local demand pattern uncertainty.
|
|
491
|
+
|
|
492
|
+
Returns
|
|
493
|
+
-------
|
|
494
|
+
dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`]
|
|
495
|
+
Local demand pattern uncertainty.
|
|
496
|
+
"""
|
|
497
|
+
return deepcopy(self.__local_demand_pattern)
|
|
498
|
+
|
|
499
|
+
@property
|
|
500
|
+
def local_elevation(self) -> dict[str, Uncertainty]:
|
|
501
|
+
"""
|
|
502
|
+
Returns the local node elevation uncertainty.
|
|
503
|
+
|
|
504
|
+
Returns
|
|
505
|
+
-------
|
|
506
|
+
dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`]
|
|
507
|
+
Local node elevation uncertainty.
|
|
213
508
|
"""
|
|
214
|
-
return deepcopy(self.
|
|
509
|
+
return deepcopy(self.__local_elevation)
|
|
510
|
+
|
|
511
|
+
@property
|
|
512
|
+
def local_constants(self) -> dict[str, Uncertainty]:
|
|
513
|
+
"""
|
|
514
|
+
Returns the local MSX constant uncertainty.
|
|
515
|
+
|
|
516
|
+
Returns
|
|
517
|
+
-------
|
|
518
|
+
dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`]
|
|
519
|
+
Local MSX constant uncertainty.
|
|
520
|
+
"""
|
|
521
|
+
return deepcopy(self.__local_constants)
|
|
522
|
+
|
|
523
|
+
@property
|
|
524
|
+
def local_parameters(self) -> dict[tuple[str, int, str], Uncertainty]:
|
|
525
|
+
"""
|
|
526
|
+
Returns the local MSX parameter uncertainty.
|
|
527
|
+
|
|
528
|
+
Returns
|
|
529
|
+
-------
|
|
530
|
+
dict[tuple[str, int, str], :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`]
|
|
531
|
+
Local MSX parameter uncertainty.
|
|
532
|
+
"""
|
|
533
|
+
return deepcopy(self.__local_parameters)
|
|
534
|
+
|
|
535
|
+
@property
|
|
536
|
+
def local_patterns(self) -> dict[str, Uncertainty]:
|
|
537
|
+
"""
|
|
538
|
+
Returns the local EPANET patterns uncertainty.
|
|
539
|
+
|
|
540
|
+
Returns
|
|
541
|
+
-------
|
|
542
|
+
dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`]
|
|
543
|
+
Local EPANET patterns uncertainty.
|
|
544
|
+
"""
|
|
545
|
+
return deepcopy(self.__local_patterns)
|
|
546
|
+
|
|
547
|
+
@property
|
|
548
|
+
def local_msx_patterns(self) -> dict[str, Uncertainty]:
|
|
549
|
+
"""
|
|
550
|
+
Returns the local EPANET-MSX patterns uncertainty.
|
|
551
|
+
|
|
552
|
+
Returns
|
|
553
|
+
-------
|
|
554
|
+
dict[str, :class:`~epyt_flow.uncertainty.uncertainties.Uncertainty`]
|
|
555
|
+
Local EPANET-MSX patterns uncertainty.
|
|
556
|
+
"""
|
|
557
|
+
return deepcopy(self.__local_msx_patterns)
|
|
215
558
|
|
|
216
559
|
def get_attributes(self) -> dict:
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
560
|
+
attribs = {"global_pipe_length_uncertainty": self.__global_pipe_length,
|
|
561
|
+
"global_pipe_roughness_uncertainty": self.__global_pipe_roughness,
|
|
562
|
+
"global_pipe_diameter_uncertainty": self.__global_pipe_diameter,
|
|
563
|
+
"global_base_demand_uncertainty": self.__global_base_demand,
|
|
564
|
+
"global_demand_pattern_uncertainty": self.__global_demand_pattern,
|
|
565
|
+
"global_elevation_uncertainty": self.__global_elevation,
|
|
566
|
+
"global_constants_uncertainty": self.__global_constants,
|
|
567
|
+
"global_parameters_uncertainty": self.__global_parameters,
|
|
568
|
+
"local_pipe_length_uncertainty": self.__local_pipe_length,
|
|
569
|
+
"local_pipe_roughness_uncertainty": self.__local_pipe_roughness,
|
|
570
|
+
"local_pipe_diameter_uncertainty": self.__local_pipe_diameter,
|
|
571
|
+
"local_base_demand_uncertainty": self.__local_base_demand,
|
|
572
|
+
"local_demand_pattern_uncertainty": self.__local_demand_pattern,
|
|
573
|
+
"local_elevation_uncertainty": self.__local_elevation,
|
|
574
|
+
"local_constants_uncertainty": self.__local_constants,
|
|
575
|
+
"local_parameters_uncertainty": self.__local_parameters,
|
|
576
|
+
"local_patterns_uncertainty": self.__local_patterns,
|
|
577
|
+
"local_msx_patterns_uncertainty": self.__local_msx_patterns}
|
|
578
|
+
|
|
579
|
+
return super().get_attributes() | attribs
|
|
225
580
|
|
|
226
581
|
def __eq__(self, other) -> bool:
|
|
227
582
|
if not isinstance(other, ModelUncertainty):
|
|
228
583
|
raise TypeError("Can not compare 'ModelUncertainty' instance " +
|
|
229
584
|
f"with '{type(other)}' instance")
|
|
230
585
|
|
|
231
|
-
return self.
|
|
232
|
-
and self.
|
|
233
|
-
and self.
|
|
234
|
-
and self.
|
|
235
|
-
and self.
|
|
236
|
-
and self.
|
|
237
|
-
and self.
|
|
586
|
+
return self.__global_pipe_length == other.global_pipe_length \
|
|
587
|
+
and self.__global_pipe_roughness == other.global_pipe_roughness \
|
|
588
|
+
and self.__global_pipe_diameter == other.global_pipe_diameter \
|
|
589
|
+
and self.__global_base_demand == other.global_base_demand \
|
|
590
|
+
and self.__global_demand_pattern == other.global_demand_pattern \
|
|
591
|
+
and self.__global_elevation == other.global_elevation \
|
|
592
|
+
and self.__global_parameters == other.global_parameters \
|
|
593
|
+
and self.__global_constants == other.global_constants \
|
|
594
|
+
and self.__local_pipe_length == other.local_pipe_length \
|
|
595
|
+
and self.__local_pipe_roughness == other.local_pipe_roughness \
|
|
596
|
+
and self.__local_pipe_diameter == other.local_pipe_diameter \
|
|
597
|
+
and self.__local_base_demand == other.local_base_demand \
|
|
598
|
+
and self.__local_demand_pattern == other.local_demand_pattern \
|
|
599
|
+
and self.__local_elevation == other.local_elevation \
|
|
600
|
+
and self.__local_parameters == other.local_parameters \
|
|
601
|
+
and self.__local_constants == other.local_constants \
|
|
602
|
+
and self.__local_patterns == other.local_patterns \
|
|
603
|
+
and self.__local_msx_patterns == other.local_msx_patterns
|
|
238
604
|
|
|
239
605
|
def __str__(self) -> str:
|
|
240
|
-
return f"
|
|
241
|
-
f"
|
|
242
|
-
f"
|
|
243
|
-
f"
|
|
606
|
+
return f"global_pipe_length: {self.__global_pipe_length} " +\
|
|
607
|
+
f"global_pipe_roughness: {self.__global_pipe_roughness} " + \
|
|
608
|
+
f"global_pipe_diameter: {self.__global_pipe_diameter} " + \
|
|
609
|
+
f"global_demand_base: {self.__global_base_demand} " + \
|
|
610
|
+
f"global_demand_pattern: {self.__global_demand_pattern} " + \
|
|
611
|
+
f"global_elevation: {self.__global_elevation} " + \
|
|
612
|
+
f"global_constants: {self.__global_constants} " + \
|
|
613
|
+
f"global_parameters: {self.__global_parameters}" + \
|
|
614
|
+
f"local_pipe_length: {self.__local_pipe_length} " +\
|
|
615
|
+
f"local_pipe_roughness: {self.__local_pipe_roughness} " + \
|
|
616
|
+
f"local_pipe_diameter: {self.__local_pipe_diameter} " + \
|
|
617
|
+
f"local_demand_base: {self.__local_base_demand} " + \
|
|
618
|
+
f"local_demand_pattern: {self.__local_demand_pattern} " + \
|
|
619
|
+
f"local_elevation: {self.__local_elevation} " + \
|
|
620
|
+
f"local_constants: {self.__local_constants} " + \
|
|
621
|
+
f"local_parameters: {self.__local_parameters} " + \
|
|
622
|
+
f"local_patterns: {self.__local_patterns} " + \
|
|
623
|
+
f"local_msx_patterns: {self.__local_msx_patterns}"
|
|
244
624
|
|
|
245
625
|
def apply(self, epanet_api: epyt.epanet) -> None:
|
|
246
626
|
"""
|
|
@@ -248,34 +628,64 @@ class ModelUncertainty(JsonSerializable):
|
|
|
248
628
|
|
|
249
629
|
Parameters
|
|
250
630
|
----------
|
|
251
|
-
epanet_api : `epyt.epanet
|
|
631
|
+
epanet_api : `epyt.epanet <https://epanet-python-toolkit-epyt.readthedocs.io/en/stable/api.html#epyt.epanet.epanet>`_
|
|
252
632
|
Interface to EPANET and EPANET-MSX.
|
|
253
633
|
"""
|
|
254
|
-
if self.
|
|
634
|
+
if self.__global_pipe_length is not None:
|
|
255
635
|
link_length = epanet_api.getLinkLength()
|
|
256
|
-
link_length = self.
|
|
636
|
+
link_length = self.__global_pipe_length.apply_batch(link_length)
|
|
257
637
|
epanet_api.setLinkLength(link_length)
|
|
258
638
|
|
|
259
|
-
if self.
|
|
639
|
+
if self.__local_pipe_length is not None:
|
|
640
|
+
for pipe_id, uncertainty in self.__local_pipe_length.items():
|
|
641
|
+
link_idx = epanet_api.getLinkIndex(pipe_id)
|
|
642
|
+
link_length = epanet_api.getLinkLength(link_idx)
|
|
643
|
+
link_length = uncertainty.apply(link_length)
|
|
644
|
+
epanet_api.setLinkLength(link_idx, link_length)
|
|
645
|
+
|
|
646
|
+
if self.__global_pipe_diameter is not None:
|
|
260
647
|
link_diameters = epanet_api.getLinkDiameter()
|
|
261
|
-
link_diameters = self.
|
|
648
|
+
link_diameters = self.__global_pipe_diameter.apply_batch(link_diameters)
|
|
262
649
|
epanet_api.setLinkDiameter(link_diameters)
|
|
263
650
|
|
|
264
|
-
if self.
|
|
651
|
+
if self.__local_pipe_diameter is not None:
|
|
652
|
+
for pipe_id, uncertainty in self.__local_pipe_diameter.items():
|
|
653
|
+
link_idx = epanet_api.getLinkIndex(pipe_id)
|
|
654
|
+
link_diameter = epanet_api.getLinkDiameter(link_idx)
|
|
655
|
+
link_diameter = uncertainty.apply(link_diameter)
|
|
656
|
+
epanet_api.setLinkDiameter(link_idx, link_diameter)
|
|
657
|
+
|
|
658
|
+
if self.__global_pipe_roughness is not None:
|
|
265
659
|
coeffs = epanet_api.getLinkRoughnessCoeff()
|
|
266
|
-
coeffs = self.
|
|
660
|
+
coeffs = self.__global_pipe_roughness.apply_batch(coeffs)
|
|
267
661
|
epanet_api.setLinkRoughnessCoeff(coeffs)
|
|
268
662
|
|
|
269
|
-
if self.
|
|
663
|
+
if self.__local_pipe_roughness is not None:
|
|
664
|
+
for pipe_id, uncertainty in self.__local_pipe_roughness.items():
|
|
665
|
+
link_idx = epanet_api.getLinkIndex(pipe_id)
|
|
666
|
+
link_roughness_coeff = epanet_api.getLinkRoughnessCoeff(link_idx)
|
|
667
|
+
link_roughness_coeff = uncertainty.apply(link_roughness_coeff)
|
|
668
|
+
epanet_api.setLinkRoughnessCoeff(link_idx, link_roughness_coeff)
|
|
669
|
+
|
|
670
|
+
if self.__global_base_demand is not None:
|
|
270
671
|
all_nodes_idx = epanet_api.getNodeIndex()
|
|
271
672
|
for node_idx in all_nodes_idx:
|
|
272
673
|
n_demand_categories = epanet_api.getNodeDemandCategoriesNumber(node_idx)
|
|
273
674
|
for demand_category in range(n_demand_categories):
|
|
274
675
|
base_demand = epanet_api.getNodeBaseDemands(node_idx)[demand_category + 1]
|
|
275
|
-
base_demand = self.
|
|
676
|
+
base_demand = self.__global_base_demand.apply(base_demand)
|
|
677
|
+
epanet_api.setNodeBaseDemands(node_idx, demand_category + 1, base_demand)
|
|
678
|
+
|
|
679
|
+
if self.__local_base_demand is not None:
|
|
680
|
+
for node_id, uncertainty in self.__local_base_demand.items():
|
|
681
|
+
node_idx = epanet_api.getNodeIndex(node_id)
|
|
682
|
+
n_demand_categories = epanet_api.getNodeDemandCategoriesNumber(node_idx)
|
|
683
|
+
for demand_category in range(n_demand_categories):
|
|
684
|
+
base_demand = epanet_api.getNodeBaseDemands(node_idx)[demand_category + 1]
|
|
685
|
+
base_demand = uncertainty.apply(base_demand)
|
|
276
686
|
epanet_api.setNodeBaseDemands(node_idx, demand_category + 1, base_demand)
|
|
277
687
|
|
|
278
|
-
if self.
|
|
688
|
+
if self.__global_demand_pattern is not None:
|
|
279
689
|
demand_patterns_idx = epanet_api.getNodeDemandPatternIndex()
|
|
280
690
|
demand_patterns_id = np.unique([demand_patterns_idx[k]
|
|
281
691
|
for k in demand_patterns_idx.keys()])
|
|
@@ -285,31 +695,98 @@ class ModelUncertainty(JsonSerializable):
|
|
|
285
695
|
pattern_length = epanet_api.getPatternLengths(pattern_id)
|
|
286
696
|
for t in range(pattern_length):
|
|
287
697
|
v = epanet_api.getPatternValue(pattern_id, t+1)
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
if self.__elevation is not None:
|
|
291
|
-
elevations = epanet_api.getNodeElevations()
|
|
292
|
-
elevations = self.__elevation.apply_batch(elevations)
|
|
293
|
-
epanet_api.setNodeElevations(elevations)
|
|
698
|
+
v_ = self.__global_demand_pattern.apply(v)
|
|
699
|
+
epanet_api.setPatternValue(pattern_id, t+1, v_)
|
|
294
700
|
|
|
295
|
-
if self.
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
epanet_api.setMSXConstantsValue(constants)
|
|
299
|
-
|
|
300
|
-
if self.__parameters is not None:
|
|
301
|
-
parameters_pipes = epanet_api.getMSXParametersPipesValue()
|
|
302
|
-
for i, pipe_idx in enumerate(epanet_api.getLinkPipeIndex()):
|
|
303
|
-
if len(parameters_pipes[i]) == 0:
|
|
304
|
-
continue
|
|
701
|
+
if self.__local_demand_pattern is not None:
|
|
702
|
+
patterns_id = epanet_api.getPatternNameID()
|
|
703
|
+
paterns_idx = epanet_api.getPatternIndex()
|
|
305
704
|
|
|
306
|
-
|
|
307
|
-
|
|
705
|
+
for pattern_id, uncertainty in self.__local_demand_pattern.items():
|
|
706
|
+
pattern_idx = paterns_idx[patterns_id.index(pattern_id)]
|
|
707
|
+
pattern_length, = epanet_api.getPatternLengths(pattern_id)
|
|
708
|
+
for t in range(pattern_length):
|
|
709
|
+
v = epanet_api.getPatternValue(pattern_idx, t+1)
|
|
710
|
+
v_ = uncertainty.apply(v)
|
|
711
|
+
epanet_api.setPatternValue(pattern_idx, t+1, v_)
|
|
308
712
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
713
|
+
if self.__global_elevation is not None:
|
|
714
|
+
elevations = epanet_api.getNodeElevations()
|
|
715
|
+
elevations = self.__global_elevation.apply_batch(elevations)
|
|
716
|
+
epanet_api.setNodeElevations(elevations)
|
|
313
717
|
|
|
314
|
-
|
|
315
|
-
|
|
718
|
+
if self.__local_elevation is not None:
|
|
719
|
+
for node_id, uncertainty in self.__local_elevation.items():
|
|
720
|
+
node_idx = epanet_api.getNodeIndex(node_id)
|
|
721
|
+
elevation = epanet_api.getNodeElevations(node_idx)
|
|
722
|
+
elevation = uncertainty.apply(elevation)
|
|
723
|
+
epanet_api.setNodeElevations(node_idx, elevation)
|
|
724
|
+
|
|
725
|
+
if self.__local_patterns is not None:
|
|
726
|
+
for pattern_id, uncertainty in self.__local_patterns.items():
|
|
727
|
+
pattern_idx = epanet_api.getPatternIndex(pattern_id)
|
|
728
|
+
pattern_length = epanet_api.getPatternLengths(pattern_idx)
|
|
729
|
+
pattern = np.array([epanet_api.getPatternValue(pattern_idx, t+1)
|
|
730
|
+
for t in range(pattern_length)])
|
|
731
|
+
pattern = uncertainty.apply_batch(pattern)
|
|
732
|
+
epanet_api.setPattern(pattern_idx, pattern)
|
|
733
|
+
|
|
734
|
+
if epanet_api.MSXFile is not None:
|
|
735
|
+
if self.__global_constants is not None:
|
|
736
|
+
constants = np.array(epanet_api.getMSXConstantsValue())
|
|
737
|
+
constants = self.__global_constants.apply_batch(constants)
|
|
738
|
+
epanet_api.setMSXConstantsValue(constants)
|
|
739
|
+
|
|
740
|
+
if self.__local_constants:
|
|
741
|
+
for constant_id, uncertainty in self.__local_constants.items():
|
|
742
|
+
idx = epanet_api.MSXgetindex(ToolkitConstants.MSX_CONSTANT, constant_id)
|
|
743
|
+
constant = epanet_api.msx.MSXgetconstant(idx)
|
|
744
|
+
constant = uncertainty.apply(constant)
|
|
745
|
+
epanet_api.msx.MSXsetconstant(idx, constant)
|
|
746
|
+
|
|
747
|
+
if self.__global_parameters is not None:
|
|
748
|
+
parameters_pipes = epanet_api.getMSXParametersPipesValue()
|
|
749
|
+
for i, pipe_idx in enumerate(epanet_api.getLinkPipeIndex()):
|
|
750
|
+
if len(parameters_pipes[i]) == 0:
|
|
751
|
+
continue
|
|
752
|
+
|
|
753
|
+
parameters_pipes_val = self.__global_parameters.apply_batch(
|
|
754
|
+
np.array(parameters_pipes[i]))
|
|
755
|
+
epanet_api.setMSXParametersPipesValue(pipe_idx, parameters_pipes_val)
|
|
756
|
+
|
|
757
|
+
parameters_tanks = epanet_api.getMSXParametersTanksValue()
|
|
758
|
+
for i, tank_idx in enumerate(epanet_api.getNodeTankIndex()):
|
|
759
|
+
if parameters_tanks[i] is None or len(parameters_tanks[i]) == 0:
|
|
760
|
+
continue
|
|
761
|
+
|
|
762
|
+
parameters_tanks_val = self.__global_parameters.apply_batch(
|
|
763
|
+
np.array(parameters_tanks[i]))
|
|
764
|
+
epanet_api.setMSXParametersTanksValue(tank_idx, parameters_tanks_val)
|
|
765
|
+
|
|
766
|
+
if self.__local_parameters is not None:
|
|
767
|
+
for (param_id, item_type, item_id), uncertainty in self.__local_parameters.items():
|
|
768
|
+
idx, = epanet_api.getMSXParametersIndex([param_id])
|
|
769
|
+
|
|
770
|
+
if item_type == ToolkitConstants.MSX_NODE:
|
|
771
|
+
item_idx = epanet_api.getNodeIndex(item_id)
|
|
772
|
+
elif item_type == ToolkitConstants.MSX_LINK:
|
|
773
|
+
item_idx = epanet_api.getLinkIndex(item_id)
|
|
774
|
+
else:
|
|
775
|
+
raise ValueError(f"Unknown item type '{item_type}' must be either " +
|
|
776
|
+
"ToolkitConstants.MSX_NODE or ToolkitConstants.MSX_LINK")
|
|
777
|
+
|
|
778
|
+
parameter = epanet_api.msx.MSXgetparameter(item_type, item_idx, idx)
|
|
779
|
+
parameter = uncertainty.apply(parameter)
|
|
780
|
+
epanet_api.msx.MSXsetparameter(item_type, item_idx, idx, parameter)
|
|
781
|
+
|
|
782
|
+
if self.__local_msx_patterns is not None:
|
|
783
|
+
for pattern_id, uncertainty in self.__local_msx_patterns.items():
|
|
784
|
+
pattern_idx, = epanet_api.getMSXPatternsIndex([pattern_id])
|
|
785
|
+
pattern = epanet_api.getMSXConstantsValue([pattern_idx])
|
|
786
|
+
pattern = uncertainty.apply_batch(pattern)
|
|
787
|
+
epanet_api.setMSXPattern(pattern_idx, pattern)
|
|
788
|
+
else:
|
|
789
|
+
if self.__local_msx_patterns is not None or self.__local_parameters is not None or \
|
|
790
|
+
self.__local_constants is not None or self.__global_constants is not None or \
|
|
791
|
+
self.__global_parameters is not None:
|
|
792
|
+
warnings.warn("Ignoring EPANET-MSX uncertainties because not .msx file was loaded")
|