floodmodeller-api 0.5.1__py3-none-any.whl → 0.5.2.post1__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.
- floodmodeller_api/__init__.py +10 -0
- floodmodeller_api/_base.py +29 -20
- floodmodeller_api/backup.py +12 -10
- floodmodeller_api/dat.py +161 -91
- floodmodeller_api/diff.py +1 -1
- floodmodeller_api/hydrology_plus/hydrology_plus_export.py +1 -1
- floodmodeller_api/ied.py +2 -4
- floodmodeller_api/ief.py +29 -17
- floodmodeller_api/ief_flags.py +1 -1
- floodmodeller_api/inp.py +4 -6
- floodmodeller_api/logs/lf.py +18 -12
- floodmodeller_api/logs/lf_helpers.py +2 -2
- floodmodeller_api/logs/lf_params.py +1 -5
- floodmodeller_api/mapping.py +9 -2
- floodmodeller_api/test/test_conveyance.py +9 -4
- floodmodeller_api/test/test_dat.py +166 -18
- floodmodeller_api/test/test_data/EX18_DAT_expected.json +164 -144
- floodmodeller_api/test/test_data/EX3_DAT_expected.json +6 -2
- floodmodeller_api/test/test_data/EX6_DAT_expected.json +12 -46
- floodmodeller_api/test/test_data/encoding_test_cp1252.dat +1081 -0
- floodmodeller_api/test/test_data/encoding_test_utf8.dat +1081 -0
- floodmodeller_api/test/test_data/integrated_bridge/AR_NoSP_NoBl_2O_NO_OneFRC.ied +33 -0
- floodmodeller_api/test/test_data/integrated_bridge/AR_vSP_25pc_1O.ied +32 -0
- floodmodeller_api/test/test_data/integrated_bridge/PL_vSP_25pc_1O.ied +34 -0
- floodmodeller_api/test/test_data/integrated_bridge/SBTwoFRCsStaggered.IED +32 -0
- floodmodeller_api/test/test_data/integrated_bridge/US_NoSP_NoBl_OR_RN.ied +28 -0
- floodmodeller_api/test/test_data/integrated_bridge/US_SP_NoBl_OR_frc_PT2-5_RN.ied +34 -0
- floodmodeller_api/test/test_data/integrated_bridge/US_fSP_NoBl_1O.ied +30 -0
- floodmodeller_api/test/test_data/integrated_bridge/US_nSP_NoBl_1O.ied +49 -0
- floodmodeller_api/test/test_data/integrated_bridge/US_vSP_NoBl_2O_Para.ied +35 -0
- floodmodeller_api/test/test_data/integrated_bridge.dat +40 -0
- floodmodeller_api/test/test_data/network.ied +2 -2
- floodmodeller_api/test/test_data/network_dat_expected.json +141 -243
- floodmodeller_api/test/test_data/network_ied_expected.json +2 -2
- floodmodeller_api/test/test_data/network_with_comments.ied +2 -2
- floodmodeller_api/test/test_ied.py +1 -1
- floodmodeller_api/test/test_ief.py +10 -2
- floodmodeller_api/test/test_integrated_bridge.py +159 -0
- floodmodeller_api/test/test_json.py +9 -3
- floodmodeller_api/test/test_logs_lf.py +45 -24
- floodmodeller_api/test/test_river.py +1 -1
- floodmodeller_api/test/test_toolbox_structure_log.py +0 -1
- floodmodeller_api/test/test_xml2d.py +5 -5
- floodmodeller_api/to_from_json.py +1 -1
- floodmodeller_api/tool.py +3 -5
- floodmodeller_api/toolbox/model_build/add_siltation_definition.py +1 -1
- floodmodeller_api/toolbox/model_build/structure_log/structure_log.py +10 -8
- floodmodeller_api/units/__init__.py +15 -0
- floodmodeller_api/units/_base.py +73 -10
- floodmodeller_api/units/_helpers.py +343 -0
- floodmodeller_api/units/boundaries.py +59 -71
- floodmodeller_api/units/comment.py +1 -1
- floodmodeller_api/units/conduits.py +57 -54
- floodmodeller_api/units/connectors.py +112 -0
- floodmodeller_api/units/controls.py +107 -0
- floodmodeller_api/units/iic.py +2 -9
- floodmodeller_api/units/losses.py +42 -42
- floodmodeller_api/units/sections.py +40 -43
- floodmodeller_api/units/structures.py +360 -530
- floodmodeller_api/units/units.py +25 -26
- floodmodeller_api/units/unsupported.py +5 -7
- floodmodeller_api/units/variables.py +2 -2
- floodmodeller_api/urban1d/_base.py +7 -8
- floodmodeller_api/urban1d/conduits.py +11 -21
- floodmodeller_api/urban1d/general_parameters.py +1 -1
- floodmodeller_api/urban1d/junctions.py +7 -11
- floodmodeller_api/urban1d/losses.py +13 -17
- floodmodeller_api/urban1d/outfalls.py +16 -21
- floodmodeller_api/urban1d/raingauges.py +3 -9
- floodmodeller_api/urban1d/subsections.py +3 -4
- floodmodeller_api/urban1d/xsections.py +11 -15
- floodmodeller_api/util.py +7 -4
- floodmodeller_api/validation/parameters.py +7 -3
- floodmodeller_api/validation/urban_parameters.py +1 -4
- floodmodeller_api/validation/validation.py +9 -4
- floodmodeller_api/version.py +1 -1
- floodmodeller_api/xml2d.py +9 -11
- floodmodeller_api/xml2d_template.py +1 -1
- floodmodeller_api/zz.py +7 -6
- {floodmodeller_api-0.5.1.dist-info → floodmodeller_api-0.5.2.post1.dist-info}/LICENSE.txt +1 -1
- {floodmodeller_api-0.5.1.dist-info → floodmodeller_api-0.5.2.post1.dist-info}/METADATA +11 -3
- {floodmodeller_api-0.5.1.dist-info → floodmodeller_api-0.5.2.post1.dist-info}/RECORD +85 -70
- {floodmodeller_api-0.5.1.dist-info → floodmodeller_api-0.5.2.post1.dist-info}/WHEEL +1 -1
- floodmodeller_api/units/helpers.py +0 -121
- {floodmodeller_api-0.5.1.dist-info → floodmodeller_api-0.5.2.post1.dist-info}/entry_points.txt +0 -0
- {floodmodeller_api-0.5.1.dist-info → floodmodeller_api-0.5.2.post1.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Flood Modeller Python API
|
|
3
|
-
Copyright (C)
|
|
3
|
+
Copyright (C) 2025 Jacobs U.K. Limited
|
|
4
4
|
|
|
5
5
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
|
|
6
6
|
as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
@@ -14,20 +14,36 @@ If you have any query about this program or this License, please contact us at s
|
|
|
14
14
|
address: Jacobs UK Limited, Flood Modeller, Cottons Centre, Cottons Lane, London, SE1 2QG, United Kingdom.
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import logging
|
|
20
|
+
|
|
17
21
|
import pandas as pd
|
|
18
22
|
|
|
19
23
|
from floodmodeller_api.validation import _validate_unit
|
|
20
24
|
|
|
21
25
|
from ._base import Unit
|
|
22
|
-
from .
|
|
23
|
-
|
|
24
|
-
_to_int,
|
|
25
|
-
_to_str,
|
|
26
|
+
from ._helpers import (
|
|
27
|
+
get_int,
|
|
26
28
|
join_10_char,
|
|
27
|
-
join_12_char_ljust,
|
|
28
29
|
join_n_char_ljust,
|
|
30
|
+
read_bridge_cross_sections,
|
|
31
|
+
read_bridge_culvert_data,
|
|
32
|
+
read_bridge_opening_data,
|
|
33
|
+
read_bridge_pier_locations,
|
|
34
|
+
read_dataframe_from_lines,
|
|
35
|
+
read_spill_section_data,
|
|
36
|
+
read_superbridge_block_data,
|
|
37
|
+
read_superbridge_opening_data,
|
|
38
|
+
set_bridge_params,
|
|
39
|
+
set_pier_params,
|
|
29
40
|
split_10_char,
|
|
30
41
|
split_n_char,
|
|
42
|
+
to_float,
|
|
43
|
+
to_int,
|
|
44
|
+
to_str,
|
|
45
|
+
write_dataframe,
|
|
46
|
+
write_dataframes,
|
|
31
47
|
)
|
|
32
48
|
|
|
33
49
|
|
|
@@ -124,235 +140,191 @@ class BRIDGE(Unit):
|
|
|
124
140
|
|
|
125
141
|
_unit = "BRIDGE"
|
|
126
142
|
|
|
127
|
-
|
|
143
|
+
# attributes set in a function (for mypy)
|
|
144
|
+
calibration_coefficient: float
|
|
145
|
+
skew: float
|
|
146
|
+
bridge_width_dual: float
|
|
147
|
+
bridge_dist_dual: float
|
|
148
|
+
total_pier_width: float
|
|
149
|
+
orifice_flow: bool
|
|
150
|
+
orifice_lower_transition_dist: float
|
|
151
|
+
orifice_upper_transition_dist: float
|
|
152
|
+
orifice_discharge_coefficient: float
|
|
153
|
+
specify_piers: bool
|
|
154
|
+
npiers: int
|
|
155
|
+
pier_use_calibration_coeff: bool
|
|
156
|
+
pier_calibration_coeff: float
|
|
157
|
+
pier_shape: str
|
|
158
|
+
soffit_shape: str
|
|
159
|
+
pier_faces: str
|
|
160
|
+
|
|
161
|
+
def _read(self, br_block: list[str]) -> None: # noqa: PLR0915
|
|
128
162
|
"""Function to read a given BRIDGE block and store data as class attributes"""
|
|
129
|
-
self.
|
|
163
|
+
self.comment = self._remove_unit_name(br_block[0])
|
|
164
|
+
self._subtype = self._get_first_word(br_block[1])
|
|
130
165
|
# Extends label line to be correct length before splitting to pick up blank labels
|
|
131
166
|
labels = split_n_char(f"{br_block[2]:<{4*self._label_len}}", self._label_len)
|
|
132
167
|
self.name = labels[0]
|
|
133
168
|
self.ds_label = labels[1]
|
|
134
169
|
self.us_remote_label = labels[2]
|
|
135
170
|
self.ds_remote_label = labels[3]
|
|
136
|
-
self.comment = br_block[0].replace("BRIDGE", "").strip()
|
|
137
171
|
|
|
138
172
|
# Read ARCH type unit
|
|
139
173
|
if self.subtype == "ARCH":
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
self.
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if params[5] == "ORIFICE":
|
|
147
|
-
self.orifice_flow = True
|
|
148
|
-
else:
|
|
149
|
-
self.orifice_flow = False
|
|
150
|
-
self.orifice_lower_transition_dist = _to_float(params[6])
|
|
151
|
-
self.orifice_upper_transition_dist = _to_float(params[7])
|
|
152
|
-
self.orifice_discharge_coefficient = _to_float(params[8], 1.0)
|
|
153
|
-
|
|
154
|
-
# Read cross section data
|
|
155
|
-
self.section_nrows = int(split_10_char(br_block[5])[0])
|
|
156
|
-
data_list = []
|
|
157
|
-
for row in br_block[6 : 6 + self.section_nrows]:
|
|
158
|
-
row_split = split_10_char(f"{row:<50}")
|
|
159
|
-
x = _to_float(row_split[0]) # chainage
|
|
160
|
-
y = _to_float(row_split[1]) # elevation
|
|
161
|
-
n = _to_float(row_split[2]) # Mannings
|
|
162
|
-
embankment = row_split[4] # Embankment flag
|
|
163
|
-
data_list.append([x, y, n, embankment])
|
|
164
|
-
self.section_data = pd.DataFrame(
|
|
165
|
-
data_list,
|
|
166
|
-
columns=["X", "Y", "Mannings n", "Embankments"],
|
|
174
|
+
set_bridge_params(self, br_block[4], include_pier=False)
|
|
175
|
+
|
|
176
|
+
self.section_nrows, end_idx, self.section_data = read_dataframe_from_lines(
|
|
177
|
+
br_block,
|
|
178
|
+
5,
|
|
179
|
+
read_bridge_cross_sections,
|
|
167
180
|
)
|
|
168
181
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
row_split = split_10_char(f"{row:<40}")
|
|
174
|
-
start = _to_float(row_split[0]) # Start (m)
|
|
175
|
-
finish = _to_float(row_split[1]) # Finish (m)
|
|
176
|
-
spring = _to_float(row_split[2]) # Springing Level
|
|
177
|
-
soffit = _to_float(row_split[3]) # Soffit Level
|
|
178
|
-
data_list.append([start, finish, spring, soffit])
|
|
179
|
-
self.opening_data = pd.DataFrame(
|
|
180
|
-
data_list,
|
|
181
|
-
columns=["Start", "Finish", "Springing Level", "Soffit Level"],
|
|
182
|
+
self.opening_nrows, end_idx, self.opening_data = read_dataframe_from_lines(
|
|
183
|
+
br_block,
|
|
184
|
+
end_idx,
|
|
185
|
+
read_bridge_opening_data,
|
|
182
186
|
)
|
|
183
187
|
|
|
184
188
|
# Read USBPR type unit
|
|
185
189
|
elif self.subtype == "USBPR1978":
|
|
186
|
-
|
|
187
|
-
params = split_10_char(f"{br_block[4]:<90}")
|
|
188
|
-
self.calibration_coefficient = _to_float(params[0], 1.0)
|
|
189
|
-
self.skew = _to_float(params[1])
|
|
190
|
-
self.bridge_width_dual = _to_float(params[2])
|
|
191
|
-
self.bridge_dist_dual = _to_float(params[3])
|
|
192
|
-
self.total_pier_width = _to_float(params[4])
|
|
193
|
-
if params[5] == "ORIFICE":
|
|
194
|
-
self.orifice_flow = True
|
|
195
|
-
else:
|
|
196
|
-
self.orifice_flow = False
|
|
197
|
-
self.orifice_lower_transition_dist = _to_float(params[6])
|
|
198
|
-
self.orifice_upper_transition_dist = _to_float(params[7])
|
|
199
|
-
self.orifice_discharge_coefficient = _to_float(params[8], 1.0)
|
|
190
|
+
set_bridge_params(self, br_block[4])
|
|
200
191
|
|
|
201
192
|
self.abutment_type = split_10_char(br_block[5])[0]
|
|
202
193
|
self.abutment_alignment = split_10_char(br_block[7])[0]
|
|
203
194
|
|
|
204
|
-
|
|
205
|
-
if int(pier_info[0]) > 0:
|
|
206
|
-
self.specify_piers = True
|
|
207
|
-
self.npiers = int(pier_info[0])
|
|
208
|
-
if pier_info[1] == "COEF":
|
|
209
|
-
self.pier_use_calibration_coeff = True
|
|
210
|
-
self.pier_calibration_coeff = _to_float(pier_info[3])
|
|
211
|
-
else:
|
|
212
|
-
self.pier_use_calibration_coeff = False
|
|
213
|
-
self.pier_shape = pier_info[1]
|
|
214
|
-
self.pier_faces = pier_info[2]
|
|
215
|
-
else:
|
|
216
|
-
self.specify_piers = False
|
|
217
|
-
self.soffit_shape = pier_info[1]
|
|
218
|
-
|
|
219
|
-
# Read cross section data
|
|
220
|
-
self.section_nrows = int(split_10_char(br_block[8])[0])
|
|
221
|
-
data_list = []
|
|
222
|
-
for row in br_block[9 : 9 + self.section_nrows]:
|
|
223
|
-
row_split = split_10_char(f"{row:<50}")
|
|
224
|
-
x = _to_float(row_split[0]) # chainage
|
|
225
|
-
y = _to_float(row_split[1]) # elevation
|
|
226
|
-
n = _to_float(row_split[2]) # Mannings
|
|
227
|
-
embankment = row_split[4] # Embankment flag
|
|
228
|
-
data_list.append([x, y, n, embankment])
|
|
229
|
-
self.section_data = pd.DataFrame(
|
|
230
|
-
data_list,
|
|
231
|
-
columns=["X", "Y", "Mannings n", "Embankments"],
|
|
232
|
-
)
|
|
195
|
+
set_pier_params(self, br_block[6])
|
|
233
196
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
end_row = start_row + self.opening_nrows
|
|
239
|
-
for row in br_block[start_row:end_row]:
|
|
240
|
-
row_split = split_10_char(f"{row:<40}")
|
|
241
|
-
start = _to_float(row_split[0]) # Start (m)
|
|
242
|
-
finish = _to_float(row_split[1]) # Finish (m)
|
|
243
|
-
spring = _to_float(row_split[2]) # Springing Level
|
|
244
|
-
soffit = _to_float(row_split[3]) # Soffit Level
|
|
245
|
-
data_list.append([start, finish, spring, soffit])
|
|
246
|
-
self.opening_data = pd.DataFrame(
|
|
247
|
-
data_list,
|
|
248
|
-
columns=["Start", "Finish", "Springing Level", "Soffit Level"],
|
|
197
|
+
self.section_nrows, end_idx, self.section_data = read_dataframe_from_lines(
|
|
198
|
+
br_block,
|
|
199
|
+
8,
|
|
200
|
+
read_bridge_cross_sections,
|
|
249
201
|
)
|
|
250
202
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
203
|
+
self.opening_nrows, end_idx, self.opening_data = read_dataframe_from_lines(
|
|
204
|
+
br_block,
|
|
205
|
+
end_idx,
|
|
206
|
+
read_bridge_opening_data,
|
|
254
207
|
)
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
invert = _to_float(row_split[0]) # Invert
|
|
261
|
-
soffit = _to_float(row_split[1]) # Soffit
|
|
262
|
-
area = _to_float(row_split[2]) # Section Area
|
|
263
|
-
cd_part = _to_float(row_split[3]) # Cd Part Full
|
|
264
|
-
cd_full = _to_float(row_split[4]) # Cd Full
|
|
265
|
-
drown = _to_float(row_split[5]) # Drowning Coefficient
|
|
266
|
-
data_list.append([invert, soffit, area, cd_part, cd_full, drown])
|
|
267
|
-
self.culvert_data = pd.DataFrame(
|
|
268
|
-
data_list,
|
|
269
|
-
columns=[
|
|
270
|
-
"Invert",
|
|
271
|
-
"Soffit",
|
|
272
|
-
"Section Area",
|
|
273
|
-
"Cd Part Full",
|
|
274
|
-
"Cd Full",
|
|
275
|
-
"Drowning Coefficient",
|
|
276
|
-
],
|
|
208
|
+
|
|
209
|
+
self.culvert_nrows, end_idx, self.culvert_data = read_dataframe_from_lines(
|
|
210
|
+
br_block,
|
|
211
|
+
end_idx,
|
|
212
|
+
read_bridge_culvert_data,
|
|
277
213
|
)
|
|
278
214
|
|
|
279
215
|
# Read Pierloss type bridge
|
|
280
216
|
elif self.subtype == "PIERLOSS":
|
|
281
217
|
# Read Params
|
|
282
|
-
|
|
283
|
-
self.calibration_coefficient =
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
self.orifice_upper_transition_dist = _to_float(params[4])
|
|
290
|
-
self.orifice_discharge_coefficient = _to_float(params[2], 1.0)
|
|
218
|
+
pierloss_params = split_10_char(f"{br_block[4]:<50}")
|
|
219
|
+
self.calibration_coefficient = to_float(pierloss_params[0], 1.0)
|
|
220
|
+
self.orifice_flow = pierloss_params[1] == "ORIFICE"
|
|
221
|
+
self.orifice_discharge_coefficient = to_float(pierloss_params[2], 1.0)
|
|
222
|
+
self.orifice_lower_transition_dist = to_float(pierloss_params[3])
|
|
223
|
+
self.orifice_upper_transition_dist = to_float(pierloss_params[4])
|
|
224
|
+
|
|
291
225
|
additional_params = split_10_char(f"{br_block[5]:<20}")
|
|
292
|
-
self.pier_coefficient =
|
|
293
|
-
self.bridge_width =
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
226
|
+
self.pier_coefficient = to_float(additional_params[0], 0.9)
|
|
227
|
+
self.bridge_width = to_float(additional_params[1])
|
|
228
|
+
|
|
229
|
+
self.us_section_nrows, end_idx, self.us_section_data = read_dataframe_from_lines(
|
|
230
|
+
br_block,
|
|
231
|
+
6,
|
|
232
|
+
read_bridge_cross_sections,
|
|
233
|
+
include_top_level=True,
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
self.ds_section_nrows, end_idx, self.ds_section_data = read_dataframe_from_lines(
|
|
237
|
+
br_block,
|
|
238
|
+
end_idx,
|
|
239
|
+
read_bridge_cross_sections,
|
|
240
|
+
include_top_level=True,
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
self.pier_locs_nrows, end_idx, self.pier_locs_data = read_dataframe_from_lines(
|
|
244
|
+
br_block,
|
|
245
|
+
end_idx,
|
|
246
|
+
read_bridge_pier_locations,
|
|
309
247
|
)
|
|
310
248
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
self.
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
249
|
+
elif self.subtype == "INTEGRATED":
|
|
250
|
+
self.revision = to_int(br_block[3])
|
|
251
|
+
self.bridge_name = br_block[4]
|
|
252
|
+
self.integrated_subtype = br_block[5].strip()
|
|
253
|
+
set_bridge_params(self, br_block[6])
|
|
254
|
+
self.abutment_type = to_int(br_block[7])
|
|
255
|
+
set_pier_params(self, br_block[8])
|
|
256
|
+
self.aligned = br_block[9].strip() == "ALIGNED"
|
|
257
|
+
|
|
258
|
+
end_idx = 10
|
|
259
|
+
self.section_nrows_list: list[int] = []
|
|
260
|
+
self.section_data_list: list[pd.DataFrame] = []
|
|
261
|
+
for _ in range(4):
|
|
262
|
+
nrows, end_idx, data = read_dataframe_from_lines(
|
|
263
|
+
br_block,
|
|
264
|
+
end_idx,
|
|
265
|
+
read_bridge_cross_sections,
|
|
266
|
+
include_panel_marker=True,
|
|
267
|
+
)
|
|
268
|
+
self.section_nrows_list.append(nrows)
|
|
269
|
+
self.section_data_list.append(data)
|
|
270
|
+
|
|
271
|
+
self.opening_type = br_block[end_idx]
|
|
272
|
+
end_idx += 1
|
|
273
|
+
self.opening_nrows = get_int(br_block[end_idx])
|
|
274
|
+
end_idx += 1
|
|
275
|
+
self.opening_nsubrows_list: list[int] = []
|
|
276
|
+
self.opening_data_list: list[pd.DataFrame] = []
|
|
277
|
+
for _ in range(self.opening_nrows):
|
|
278
|
+
nrows, end_idx, data = read_dataframe_from_lines(
|
|
279
|
+
br_block,
|
|
280
|
+
end_idx,
|
|
281
|
+
read_superbridge_opening_data,
|
|
282
|
+
)
|
|
283
|
+
self.opening_nsubrows_list.append(nrows)
|
|
284
|
+
self.opening_data_list.append(data)
|
|
285
|
+
|
|
286
|
+
self.culvert_nrows, end_idx, self.culvert_data = read_dataframe_from_lines(
|
|
287
|
+
br_block,
|
|
288
|
+
end_idx,
|
|
289
|
+
read_bridge_culvert_data,
|
|
326
290
|
)
|
|
327
291
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
self.
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
292
|
+
spill_params = split_10_char(f"{br_block[end_idx]:<30}")
|
|
293
|
+
self.weir_coefficient = to_float(spill_params[1])
|
|
294
|
+
self.modular_limit = to_float(spill_params[2])
|
|
295
|
+
self.spill_nrows, end_idx, self.spill_data = read_dataframe_from_lines(
|
|
296
|
+
br_block,
|
|
297
|
+
end_idx,
|
|
298
|
+
read_spill_section_data,
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
self.block_comment = br_block[end_idx]
|
|
302
|
+
end_idx += 1
|
|
303
|
+
block_params = split_10_char(f"{br_block[end_idx]:<50}")
|
|
304
|
+
self.inlet_loss = to_float(block_params[1])
|
|
305
|
+
self.outlet_loss = to_float(block_params[2])
|
|
306
|
+
self.block_method = "USDEPTH" if (block_params[3] == "") else block_params[3]
|
|
307
|
+
self.override = block_params[4] == "OVERRIDE"
|
|
308
|
+
self.block_nrows, end_idx, self.block_data = read_dataframe_from_lines(
|
|
309
|
+
br_block,
|
|
310
|
+
end_idx,
|
|
311
|
+
read_superbridge_block_data,
|
|
342
312
|
)
|
|
343
313
|
|
|
344
314
|
else:
|
|
345
|
-
# This else block is triggered for bridge subtypes which aren't yet supported
|
|
346
|
-
|
|
347
|
-
|
|
315
|
+
# This else block is triggered for bridge subtypes which aren't yet supported
|
|
316
|
+
# and just keeps the 'br_block' in its raw state to write back.
|
|
317
|
+
logging.warning(
|
|
318
|
+
"This Bridge sub-type: '%s' is currently unsupported for reading/editing",
|
|
319
|
+
self.subtype,
|
|
348
320
|
)
|
|
349
321
|
self._raw_block = br_block
|
|
350
322
|
self.name = br_block[2][:12].strip()
|
|
351
323
|
|
|
352
|
-
def _write(self): # noqa:
|
|
324
|
+
def _write(self) -> list[str]: # noqa: PLR0915
|
|
353
325
|
"""Function to write a valid BRIDGE block"""
|
|
354
326
|
_validate_unit(self) # Function to check the params are valid for BRIDGE unit
|
|
355
|
-
header =
|
|
327
|
+
header = self._create_header()
|
|
356
328
|
labels = join_n_char_ljust(
|
|
357
329
|
self._label_len,
|
|
358
330
|
self.name,
|
|
@@ -375,25 +347,14 @@ class BRIDGE(Unit):
|
|
|
375
347
|
self.orifice_upper_transition_dist,
|
|
376
348
|
self.orifice_discharge_coefficient,
|
|
377
349
|
)
|
|
378
|
-
|
|
379
|
-
br_block.extend(["MANNING", params, f"{self.section_nrows!s:>10}"])
|
|
380
|
-
|
|
381
|
-
section_data = []
|
|
382
|
-
for _, x, y, n, embankments in self.section_data.itertuples():
|
|
383
|
-
# Adding extra 10 spaces before embankment flag
|
|
384
|
-
row = join_10_char(x, y, n, "")
|
|
385
|
-
row += embankments
|
|
386
|
-
section_data.append(row)
|
|
350
|
+
br_block.extend(["MANNING", params])
|
|
387
351
|
|
|
352
|
+
self.section_nrows = len(self.section_data)
|
|
353
|
+
section_data = write_dataframe(self.section_nrows, self.section_data, empty=3)
|
|
388
354
|
br_block.extend(section_data)
|
|
389
355
|
|
|
390
356
|
self.opening_nrows = len(self.opening_data)
|
|
391
|
-
|
|
392
|
-
opening_data = []
|
|
393
|
-
for _, start, finish, spring, soffit in self.opening_data.itertuples():
|
|
394
|
-
row = join_10_char(start, finish, spring, soffit)
|
|
395
|
-
opening_data.append(row)
|
|
396
|
-
|
|
357
|
+
opening_data = write_dataframe(self.opening_nrows, self.opening_data)
|
|
397
358
|
br_block.extend(opening_data)
|
|
398
359
|
|
|
399
360
|
return br_block
|
|
@@ -413,13 +374,12 @@ class BRIDGE(Unit):
|
|
|
413
374
|
)
|
|
414
375
|
if self.specify_piers:
|
|
415
376
|
if self.pier_use_calibration_coeff:
|
|
416
|
-
pier_params = f'{self.npiers:>10}{"
|
|
377
|
+
pier_params = f'{self.npiers:>10}{"COEFF":<10}{"":>10}{self.pier_calibration_coeff:>10.3f}'
|
|
417
378
|
else:
|
|
418
379
|
pier_params = f"{self.npiers:>10}{self.pier_shape:<10}{self.pier_faces:<10}"
|
|
419
380
|
else:
|
|
420
381
|
pier_params = f"{0:>10}{self.soffit_shape}"
|
|
421
382
|
|
|
422
|
-
self.section_nrows = len(self.section_data)
|
|
423
383
|
br_block.extend(
|
|
424
384
|
[
|
|
425
385
|
"MANNING",
|
|
@@ -427,40 +387,19 @@ class BRIDGE(Unit):
|
|
|
427
387
|
f"{self.abutment_type!s:>10}",
|
|
428
388
|
pier_params,
|
|
429
389
|
self.abutment_alignment,
|
|
430
|
-
f"{self.section_nrows!s:>10}",
|
|
431
390
|
],
|
|
432
391
|
)
|
|
433
392
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
# Adding extra 10 spaces before embankment flag
|
|
437
|
-
row = join_10_char(x, y, n, "")
|
|
438
|
-
row += embankments
|
|
439
|
-
section_data.append(row)
|
|
393
|
+
self.section_nrows = len(self.section_data)
|
|
394
|
+
section_data = write_dataframe(self.section_nrows, self.section_data, empty=3)
|
|
440
395
|
br_block.extend(section_data)
|
|
441
396
|
|
|
442
397
|
self.opening_nrows = len(self.opening_data)
|
|
443
|
-
|
|
444
|
-
opening_data = []
|
|
445
|
-
for _, start, finish, spring, soffit in self.opening_data.itertuples():
|
|
446
|
-
row = join_10_char(start, finish, spring, soffit)
|
|
447
|
-
opening_data.append(row)
|
|
398
|
+
opening_data = write_dataframe(self.opening_nrows, self.opening_data)
|
|
448
399
|
br_block.extend(opening_data)
|
|
449
400
|
|
|
450
401
|
self.culvert_nrows = len(self.culvert_data)
|
|
451
|
-
|
|
452
|
-
culvert_data = []
|
|
453
|
-
for (
|
|
454
|
-
_,
|
|
455
|
-
invert,
|
|
456
|
-
soffit,
|
|
457
|
-
area,
|
|
458
|
-
cd_part,
|
|
459
|
-
cd_full,
|
|
460
|
-
drown,
|
|
461
|
-
) in self.culvert_data.itertuples():
|
|
462
|
-
row = join_10_char(invert, soffit, area, cd_part, cd_full, drown)
|
|
463
|
-
culvert_data.append(row)
|
|
402
|
+
culvert_data = write_dataframe(self.culvert_nrows, self.culvert_data)
|
|
464
403
|
br_block.extend(culvert_data)
|
|
465
404
|
|
|
466
405
|
return br_block
|
|
@@ -475,52 +414,105 @@ class BRIDGE(Unit):
|
|
|
475
414
|
self.orifice_upper_transition_dist,
|
|
476
415
|
)
|
|
477
416
|
additional_params = join_10_char(self.pier_coefficient, self.bridge_width)
|
|
478
|
-
|
|
479
|
-
br_block.extend(
|
|
480
|
-
[
|
|
481
|
-
"YARNELL",
|
|
482
|
-
params,
|
|
483
|
-
additional_params,
|
|
484
|
-
f"{self.us_section_nrows!s:>10}",
|
|
485
|
-
],
|
|
486
|
-
)
|
|
417
|
+
br_block.extend(["YARNELL", params, additional_params])
|
|
487
418
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
# Adding extra 10 spaces before embankment flag
|
|
491
|
-
row = join_10_char(x, y, n, "")
|
|
492
|
-
row += f"{embankments:<10}"
|
|
493
|
-
row += join_10_char(top_level)
|
|
494
|
-
us_section_data.append(row)
|
|
419
|
+
self.us_section_nrows = len(self.us_section_data)
|
|
420
|
+
us_section_data = write_dataframe(self.us_section_nrows, self.us_section_data, empty=3)
|
|
495
421
|
br_block.extend(us_section_data)
|
|
496
422
|
|
|
497
423
|
self.ds_section_nrows = len(self.ds_section_data)
|
|
498
|
-
|
|
499
|
-
ds_section_data = []
|
|
500
|
-
for _, x, y, n, embankments, top_level in self.ds_section_data.itertuples():
|
|
501
|
-
# Adding extra 10 spaces before embankment flag
|
|
502
|
-
row = join_10_char(x, y, n, "")
|
|
503
|
-
row += f"{embankments:<10}"
|
|
504
|
-
row += join_10_char(top_level)
|
|
505
|
-
ds_section_data.append(row)
|
|
424
|
+
ds_section_data = write_dataframe(self.ds_section_nrows, self.ds_section_data, empty=3)
|
|
506
425
|
br_block.extend(ds_section_data)
|
|
507
426
|
|
|
508
427
|
self.pier_locs_nrows = len(self.pier_locs_data)
|
|
509
|
-
|
|
510
|
-
pier_locs_data = []
|
|
511
|
-
for (
|
|
512
|
-
_,
|
|
513
|
-
l_x,
|
|
514
|
-
l_top_level,
|
|
515
|
-
r_x,
|
|
516
|
-
r_top_level,
|
|
517
|
-
) in self.pier_locs_data.itertuples():
|
|
518
|
-
row = join_10_char(l_x, l_top_level, r_x, r_top_level)
|
|
519
|
-
pier_locs_data.append(row)
|
|
428
|
+
pier_locs_data = write_dataframe(self.pier_locs_nrows, self.pier_locs_data)
|
|
520
429
|
br_block.extend(pier_locs_data)
|
|
521
430
|
|
|
522
431
|
return br_block
|
|
523
432
|
|
|
433
|
+
if self.subtype == "INTEGRATED":
|
|
434
|
+
line_1_2 = br_block
|
|
435
|
+
line_3 = str(self.revision)
|
|
436
|
+
line_4 = self.bridge_name
|
|
437
|
+
line_5 = self.integrated_subtype
|
|
438
|
+
line_6 = join_10_char(
|
|
439
|
+
self.calibration_coefficient,
|
|
440
|
+
self.skew,
|
|
441
|
+
self.bridge_width_dual,
|
|
442
|
+
self.bridge_dist_dual,
|
|
443
|
+
self.total_pier_width,
|
|
444
|
+
"ORIFICE" if self.orifice_flow else "",
|
|
445
|
+
self.orifice_lower_transition_dist,
|
|
446
|
+
self.orifice_upper_transition_dist,
|
|
447
|
+
self.orifice_discharge_coefficient,
|
|
448
|
+
)
|
|
449
|
+
line_7 = str(self.abutment_type)
|
|
450
|
+
if self.specify_piers:
|
|
451
|
+
if self.pier_use_calibration_coeff:
|
|
452
|
+
line_8 = join_10_char(
|
|
453
|
+
self.npiers,
|
|
454
|
+
"COEFF",
|
|
455
|
+
"",
|
|
456
|
+
self.pier_calibration_coeff,
|
|
457
|
+
)
|
|
458
|
+
else:
|
|
459
|
+
line_8 = join_10_char(
|
|
460
|
+
self.npiers,
|
|
461
|
+
self.pier_shape,
|
|
462
|
+
self.pier_faces,
|
|
463
|
+
)
|
|
464
|
+
else:
|
|
465
|
+
line_8 = join_10_char(
|
|
466
|
+
0,
|
|
467
|
+
self.soffit_shape,
|
|
468
|
+
)
|
|
469
|
+
line_9 = "ALIGNED" if self.aligned else ""
|
|
470
|
+
line_10_11_12_13 = write_dataframes(
|
|
471
|
+
None,
|
|
472
|
+
self.section_nrows_list,
|
|
473
|
+
self.section_data_list,
|
|
474
|
+
)
|
|
475
|
+
line_14 = self.opening_type
|
|
476
|
+
line_15 = write_dataframes(
|
|
477
|
+
self.opening_nrows,
|
|
478
|
+
self.opening_nsubrows_list,
|
|
479
|
+
self.opening_data_list,
|
|
480
|
+
)
|
|
481
|
+
line_16 = write_dataframe(self.culvert_nrows, self.culvert_data)
|
|
482
|
+
line_17 = write_dataframe(
|
|
483
|
+
join_10_char(self.spill_nrows, self.weir_coefficient, self.modular_limit),
|
|
484
|
+
self.spill_data,
|
|
485
|
+
)
|
|
486
|
+
line_18 = self.block_comment
|
|
487
|
+
line_19 = write_dataframe(
|
|
488
|
+
join_10_char(
|
|
489
|
+
self.block_nrows,
|
|
490
|
+
self.inlet_loss,
|
|
491
|
+
self.outlet_loss,
|
|
492
|
+
self.block_method,
|
|
493
|
+
"OVERRIDE" if self.override else "NOOVERRIDE",
|
|
494
|
+
),
|
|
495
|
+
self.block_data,
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
return [
|
|
499
|
+
*line_1_2,
|
|
500
|
+
line_3,
|
|
501
|
+
line_4,
|
|
502
|
+
line_5, # type: ignore
|
|
503
|
+
line_6,
|
|
504
|
+
line_7,
|
|
505
|
+
line_8,
|
|
506
|
+
line_9,
|
|
507
|
+
*line_10_11_12_13,
|
|
508
|
+
line_14,
|
|
509
|
+
*line_15,
|
|
510
|
+
*line_16,
|
|
511
|
+
*line_17,
|
|
512
|
+
line_18,
|
|
513
|
+
*line_19,
|
|
514
|
+
]
|
|
515
|
+
|
|
524
516
|
return self._raw_block
|
|
525
517
|
|
|
526
518
|
|
|
@@ -594,41 +586,41 @@ class SLUICE(Unit):
|
|
|
594
586
|
|
|
595
587
|
def _read(self, block):
|
|
596
588
|
"""Function to read a given SLUICE block and store data as class attributes"""
|
|
597
|
-
self._subtype = block[1]
|
|
589
|
+
self._subtype = self._get_first_word(block[1])
|
|
598
590
|
|
|
599
591
|
# Extends label line to be correct length before splitting to pick up blank labels
|
|
600
592
|
labels = split_n_char(f"{block[2]:<{3*self._label_len}}", self._label_len)
|
|
601
593
|
self.name = labels[0]
|
|
602
594
|
self.ds_label = labels[1]
|
|
603
595
|
self.remote_label = labels[2]
|
|
604
|
-
self.comment = block[0]
|
|
596
|
+
self.comment = self._remove_unit_name(block[0])
|
|
605
597
|
|
|
606
598
|
# First parameter line
|
|
607
599
|
params1 = split_10_char(f"{block[3]:<80}")
|
|
608
|
-
self.weir_flow_coefficient =
|
|
609
|
-
self.under_gate_flow =
|
|
610
|
-
self.weir_breadth =
|
|
611
|
-
self.crest_elevation =
|
|
612
|
-
self.gate_height_or_chord =
|
|
613
|
-
self.weir_length =
|
|
600
|
+
self.weir_flow_coefficient = to_float(params1[0], 1.0)
|
|
601
|
+
self.under_gate_flow = to_float(params1[1], 1.0)
|
|
602
|
+
self.weir_breadth = to_float(params1[2])
|
|
603
|
+
self.crest_elevation = to_float(params1[3])
|
|
604
|
+
self.gate_height_or_chord = to_float(params1[4])
|
|
605
|
+
self.weir_length = to_float(params1[5])
|
|
614
606
|
if self.subtype == "RADIAL":
|
|
615
607
|
self.use_degrees = params1[6] == "DEGREES"
|
|
616
608
|
self.allow_free_flow_under = params1[7] == "FREESLUICE"
|
|
617
609
|
|
|
618
610
|
# Second parameter line
|
|
619
611
|
params2 = split_10_char(f"{block[4]:<70}")
|
|
620
|
-
self.us_weir_height =
|
|
621
|
-
self.ds_weir_height =
|
|
622
|
-
self.bias_factor =
|
|
623
|
-
self.over_gate_flow =
|
|
612
|
+
self.us_weir_height = to_float(params2[0])
|
|
613
|
+
self.ds_weir_height = to_float(params2[1])
|
|
614
|
+
self.bias_factor = to_float(params2[2], 1.0)
|
|
615
|
+
self.over_gate_flow = to_float(params2[3], 1.0)
|
|
624
616
|
if self.subtype == "RADIAL":
|
|
625
|
-
self.pivot_height =
|
|
626
|
-
self.gate_radius =
|
|
617
|
+
self.pivot_height = to_float(params2[4], 0.7)
|
|
618
|
+
self.gate_radius = to_float(params2[5], 0.7)
|
|
627
619
|
else:
|
|
628
620
|
self.modular_limits = {
|
|
629
|
-
"weir_flow":
|
|
630
|
-
"under_gate_flow":
|
|
631
|
-
"over_gate_flow":
|
|
621
|
+
"weir_flow": to_float(params2[4]),
|
|
622
|
+
"under_gate_flow": to_float(params2[5], 1.0),
|
|
623
|
+
"over_gate_flow": to_float(params2[6], 1.0),
|
|
632
624
|
}
|
|
633
625
|
|
|
634
626
|
# Third parameter line
|
|
@@ -636,15 +628,15 @@ class SLUICE(Unit):
|
|
|
636
628
|
self.ngates = int(params3[0]) # number of gates
|
|
637
629
|
if self.subtype == "RADIAL":
|
|
638
630
|
self.modular_limits = {
|
|
639
|
-
"weir_flow":
|
|
640
|
-
"under_gate_flow":
|
|
641
|
-
"over_gate_flow":
|
|
631
|
+
"weir_flow": to_float(params3[1]),
|
|
632
|
+
"under_gate_flow": to_float(params3[2], 1.0),
|
|
633
|
+
"over_gate_flow": to_float(params3[3], 1.0),
|
|
642
634
|
}
|
|
643
|
-
self.timeunit =
|
|
644
|
-
self.extendmethod =
|
|
635
|
+
self.timeunit = to_str(params3[4], "SECONDS", check_float=True)
|
|
636
|
+
self.extendmethod = to_str(params3[5], "EXTEND")
|
|
645
637
|
else:
|
|
646
|
-
self.timeunit =
|
|
647
|
-
self.extendmethod =
|
|
638
|
+
self.timeunit = to_str(params3[1], "SECONDS", check_float=True)
|
|
639
|
+
self.extendmethod = to_str(params3[2], "EXTEND")
|
|
648
640
|
|
|
649
641
|
# Control lines
|
|
650
642
|
self.control_method = block[6].split()[0].upper()
|
|
@@ -661,14 +653,15 @@ class SLUICE(Unit):
|
|
|
661
653
|
|
|
662
654
|
else:
|
|
663
655
|
self._raw_extra_lines = block[6:]
|
|
664
|
-
|
|
665
|
-
|
|
656
|
+
logging.warning(
|
|
657
|
+
"Note: Sluice control using method: '%s' is not currently supported.",
|
|
658
|
+
self.control_method,
|
|
666
659
|
)
|
|
667
660
|
|
|
668
661
|
def _write(self):
|
|
669
662
|
"""Function to write a valid SLUICE block"""
|
|
670
663
|
_validate_unit(self) # Function to check the params are valid for CONDUIT unit
|
|
671
|
-
header =
|
|
664
|
+
header = self._create_header()
|
|
672
665
|
labels = join_n_char_ljust(self._label_len, self.name, self.ds_label, self.remote_label)
|
|
673
666
|
block = [header, self.subtype, labels]
|
|
674
667
|
|
|
@@ -763,8 +756,8 @@ class SLUICE(Unit):
|
|
|
763
756
|
data_list = []
|
|
764
757
|
for row in block[gate_row + 2 : gate_row + 2 + nrows]:
|
|
765
758
|
row_split = split_10_char(f"{row:<20}")
|
|
766
|
-
x =
|
|
767
|
-
y =
|
|
759
|
+
x = to_float(row_split[0]) # time
|
|
760
|
+
y = to_float(row_split[1]) # opening
|
|
768
761
|
data_list.append([x, y])
|
|
769
762
|
|
|
770
763
|
gate_data = pd.DataFrame(data_list, columns=["Time", "Opening"])
|
|
@@ -785,9 +778,9 @@ class SLUICE(Unit):
|
|
|
785
778
|
data_list = []
|
|
786
779
|
for row in block[gate_row + 2 : gate_row + 2 + nrows]:
|
|
787
780
|
row_split = split_10_char(f"{row:<30}")
|
|
788
|
-
x =
|
|
781
|
+
x = to_float(row_split[0]) # time
|
|
789
782
|
y = row_split[1] # mode
|
|
790
|
-
z =
|
|
783
|
+
z = to_float(row_split[2]) # opening
|
|
791
784
|
data_list.append([x, y, z])
|
|
792
785
|
|
|
793
786
|
gate_data = pd.DataFrame(data_list, columns=["Time", "Mode", "Opening"])
|
|
@@ -830,34 +823,34 @@ class ORIFICE(Unit):
|
|
|
830
823
|
|
|
831
824
|
def _read(self, block):
|
|
832
825
|
"""Function to read a given ORIFICE block and store data as class attributes"""
|
|
833
|
-
self._subtype = block[1]
|
|
826
|
+
self._subtype = self._get_first_word(block[1])
|
|
834
827
|
self.flapped = self.subtype == "FLAPPED"
|
|
835
828
|
|
|
836
829
|
# Extends label line to be correct length before splitting to pick up blank labels
|
|
837
830
|
labels = split_n_char(f"{block[2]:<{2*self._label_len}}", self._label_len)
|
|
838
831
|
self.name = labels[0]
|
|
839
832
|
self.ds_label = labels[1]
|
|
840
|
-
self.comment = block[0]
|
|
833
|
+
self.comment = self._remove_unit_name(block[0])
|
|
841
834
|
|
|
842
835
|
# First parameter line
|
|
843
836
|
params1 = split_10_char(f"{block[3]:<60}")
|
|
844
|
-
self.invert =
|
|
845
|
-
self.soffit =
|
|
846
|
-
self.bore_area =
|
|
847
|
-
self.upstream_sill =
|
|
848
|
-
self.downstream_sill =
|
|
849
|
-
self.shape =
|
|
837
|
+
self.invert = to_float(params1[0])
|
|
838
|
+
self.soffit = to_float(params1[1])
|
|
839
|
+
self.bore_area = to_float(params1[2])
|
|
840
|
+
self.upstream_sill = to_float(params1[3])
|
|
841
|
+
self.downstream_sill = to_float(params1[4])
|
|
842
|
+
self.shape = to_str(params1[5], "RECTANGLE")
|
|
850
843
|
|
|
851
844
|
# Second parameter line
|
|
852
845
|
params2 = split_10_char(block[4])
|
|
853
|
-
self.weir_flow =
|
|
854
|
-
self.surcharged_flow =
|
|
855
|
-
self.modular_limit =
|
|
846
|
+
self.weir_flow = to_float(params2[0], 1.0)
|
|
847
|
+
self.surcharged_flow = to_float(params2[1], 1.0)
|
|
848
|
+
self.modular_limit = to_float(params2[2], 0.7)
|
|
856
849
|
|
|
857
850
|
def _write(self):
|
|
858
851
|
"""Function to write a valid ORIFICE block"""
|
|
859
852
|
_validate_unit(self) # Function to check the params are valid for CONDUIT unit
|
|
860
|
-
header =
|
|
853
|
+
header = self._create_header()
|
|
861
854
|
labels = join_n_char_ljust(self._label_len, self.name, self.ds_label)
|
|
862
855
|
|
|
863
856
|
self._subtype = "FLAPPED" if self.flapped else "OPEN"
|
|
@@ -938,31 +931,20 @@ class SPILL(Unit):
|
|
|
938
931
|
labels = split_n_char(f"{block[1]:<{2*self._label_len}}", self._label_len)
|
|
939
932
|
self.name = labels[0]
|
|
940
933
|
self.ds_label = labels[1]
|
|
941
|
-
self.comment = block[0]
|
|
934
|
+
self.comment = self._remove_unit_name(block[0])
|
|
942
935
|
|
|
943
936
|
# First parameter line
|
|
944
937
|
params = split_10_char(block[2])
|
|
945
|
-
self.weir_coefficient =
|
|
946
|
-
self.modular_limit =
|
|
938
|
+
self.weir_coefficient = to_float(params[0], 1.2)
|
|
939
|
+
self.modular_limit = to_float(params[1], 0.9)
|
|
947
940
|
|
|
948
941
|
# Spill section data
|
|
949
|
-
|
|
950
|
-
for row in block[4:]:
|
|
951
|
-
row_split = split_10_char(f"{row:<40}")
|
|
952
|
-
x = _to_float(row_split[0]) # chainage
|
|
953
|
-
y = _to_float(row_split[1]) # elevation
|
|
954
|
-
e = _to_float(row_split[2]) # easting
|
|
955
|
-
n = _to_float(row_split[3]) # northing
|
|
956
|
-
|
|
957
|
-
data_list.append([x, y, e, n])
|
|
958
|
-
|
|
959
|
-
spill_data = pd.DataFrame(data_list, columns=["X", "Y", "Easting", "Northing"])
|
|
960
|
-
self.data = spill_data
|
|
942
|
+
self.data = read_spill_section_data(block[4:])
|
|
961
943
|
|
|
962
944
|
def _write(self):
|
|
963
945
|
"""Function to write a valid SPILL block"""
|
|
964
946
|
_validate_unit(self) # Function to check the params are valid for CONDUIT unit
|
|
965
|
-
header =
|
|
947
|
+
header = self._create_header()
|
|
966
948
|
labels = join_n_char_ljust(self._label_len, self.name, self.ds_label)
|
|
967
949
|
block = [header, labels]
|
|
968
950
|
|
|
@@ -1030,25 +1012,25 @@ class RNWEIR(Unit):
|
|
|
1030
1012
|
labels = split_n_char(f"{block[1]:<{2*self._label_len}}", self._label_len)
|
|
1031
1013
|
self.name = labels[0]
|
|
1032
1014
|
self.ds_label = labels[1]
|
|
1033
|
-
self.comment = block[0]
|
|
1015
|
+
self.comment = self._remove_unit_name(block[0])
|
|
1034
1016
|
|
|
1035
1017
|
# First parameter line
|
|
1036
1018
|
params1 = split_10_char(f"{block[2]:<50}")
|
|
1037
|
-
self.velocity_coefficient =
|
|
1038
|
-
self.weir_length =
|
|
1039
|
-
self.weir_breadth =
|
|
1040
|
-
self.weir_elevation =
|
|
1041
|
-
self.modular_limit =
|
|
1019
|
+
self.velocity_coefficient = to_float(params1[0])
|
|
1020
|
+
self.weir_length = to_float(params1[1])
|
|
1021
|
+
self.weir_breadth = to_float(params1[2])
|
|
1022
|
+
self.weir_elevation = to_float(params1[3])
|
|
1023
|
+
self.modular_limit = to_float(params1[4])
|
|
1042
1024
|
|
|
1043
1025
|
# Second parameter line
|
|
1044
1026
|
params2 = split_10_char(f"{block[3]:<20}")
|
|
1045
|
-
self.upstream_crest_height =
|
|
1046
|
-
self.downstream_crest_height =
|
|
1027
|
+
self.upstream_crest_height = to_float(params2[0])
|
|
1028
|
+
self.downstream_crest_height = to_float(params2[1])
|
|
1047
1029
|
|
|
1048
1030
|
def _write(self):
|
|
1049
1031
|
"""Function to write a valid RNWEIR block"""
|
|
1050
1032
|
_validate_unit(self)
|
|
1051
|
-
header =
|
|
1033
|
+
header = self._create_header()
|
|
1052
1034
|
labels = join_n_char_ljust(self._label_len, self.name, self.ds_label)
|
|
1053
1035
|
block = [header, labels]
|
|
1054
1036
|
|
|
@@ -1131,23 +1113,23 @@ class WEIR(Unit):
|
|
|
1131
1113
|
labels = split_n_char(f"{block[1]:<{2*self._label_len}}", self._label_len)
|
|
1132
1114
|
self.name = labels[0]
|
|
1133
1115
|
self.ds_label = labels[1]
|
|
1134
|
-
self.comment = block[0]
|
|
1116
|
+
self.comment = self._remove_unit_name(block[0])
|
|
1135
1117
|
|
|
1136
1118
|
# Exponent
|
|
1137
|
-
self.exponent =
|
|
1119
|
+
self.exponent = to_float(block[2].strip())
|
|
1138
1120
|
|
|
1139
1121
|
# Parameters line
|
|
1140
1122
|
params = split_10_char(f"{block[3]:<50}")
|
|
1141
|
-
self.discharge_coefficient =
|
|
1142
|
-
self.velocity_coefficient =
|
|
1143
|
-
self.weir_breadth =
|
|
1144
|
-
self.weir_elevation =
|
|
1145
|
-
self.modular_limit =
|
|
1123
|
+
self.discharge_coefficient = to_float(params[0])
|
|
1124
|
+
self.velocity_coefficient = to_float(params[1])
|
|
1125
|
+
self.weir_breadth = to_float(params[2])
|
|
1126
|
+
self.weir_elevation = to_float(params[3])
|
|
1127
|
+
self.modular_limit = to_float(params[4])
|
|
1146
1128
|
|
|
1147
1129
|
def _write(self):
|
|
1148
1130
|
"""Function to write a valid WEIR block"""
|
|
1149
1131
|
_validate_unit(self)
|
|
1150
|
-
header =
|
|
1132
|
+
header = self._create_header()
|
|
1151
1133
|
labels = join_n_char_ljust(self._label_len, self.name, self.ds_label)
|
|
1152
1134
|
block = [header, labels]
|
|
1153
1135
|
|
|
@@ -1225,24 +1207,24 @@ class CRUMP(Unit):
|
|
|
1225
1207
|
self.ds_label = labels[1]
|
|
1226
1208
|
self.us_remote_label = labels[2]
|
|
1227
1209
|
self.ds_remote_label = labels[3]
|
|
1228
|
-
self.comment = block[0]
|
|
1210
|
+
self.comment = self._remove_unit_name(block[0])
|
|
1229
1211
|
|
|
1230
1212
|
# First parameter line
|
|
1231
1213
|
params1 = split_10_char(f"{block[2]:<40}")
|
|
1232
|
-
self.calibration_coefficient =
|
|
1233
|
-
self.weir_breadth =
|
|
1234
|
-
self.weir_elevation =
|
|
1235
|
-
self.modular_limit =
|
|
1214
|
+
self.calibration_coefficient = to_float(params1[0])
|
|
1215
|
+
self.weir_breadth = to_float(params1[1])
|
|
1216
|
+
self.weir_elevation = to_float(params1[2])
|
|
1217
|
+
self.modular_limit = to_float(params1[3])
|
|
1236
1218
|
|
|
1237
1219
|
# Second parameter line
|
|
1238
1220
|
params2 = split_10_char(f"{block[3]:<20}")
|
|
1239
|
-
self.upstream_crest_height =
|
|
1240
|
-
self.downstream_crest_height =
|
|
1221
|
+
self.upstream_crest_height = to_float(params2[0])
|
|
1222
|
+
self.downstream_crest_height = to_float(params2[1])
|
|
1241
1223
|
|
|
1242
1224
|
def _write(self):
|
|
1243
1225
|
"""Function to write a valid CRUMP block"""
|
|
1244
1226
|
_validate_unit(self)
|
|
1245
|
-
header =
|
|
1227
|
+
header = self._create_header()
|
|
1246
1228
|
labels = join_n_char_ljust(
|
|
1247
1229
|
self._label_len,
|
|
1248
1230
|
self.name,
|
|
@@ -1334,30 +1316,30 @@ class FLAT_V_WEIR(Unit): # noqa: N801
|
|
|
1334
1316
|
self.ds_label = labels[1]
|
|
1335
1317
|
self.us_remote_label = labels[2]
|
|
1336
1318
|
self.ds_remote_label = labels[3]
|
|
1337
|
-
self.comment = block[0]
|
|
1319
|
+
self.comment = self._remove_unit_name(block[0])
|
|
1338
1320
|
|
|
1339
1321
|
# First parameter line
|
|
1340
1322
|
params1 = split_10_char(f"{block[2]:<90}")
|
|
1341
|
-
self.calibration_coefficient =
|
|
1342
|
-
self.weir_breadth =
|
|
1343
|
-
self.weir_elevation =
|
|
1344
|
-
self.modular_limit =
|
|
1345
|
-
self.v_slope =
|
|
1346
|
-
self.side_slope =
|
|
1347
|
-
self.ds_face_slope =
|
|
1348
|
-
self.coriolis_coefficient =
|
|
1349
|
-
self.bank_top_elevation =
|
|
1323
|
+
self.calibration_coefficient = to_float(params1[0])
|
|
1324
|
+
self.weir_breadth = to_float(params1[1])
|
|
1325
|
+
self.weir_elevation = to_float(params1[2])
|
|
1326
|
+
self.modular_limit = to_float(params1[3])
|
|
1327
|
+
self.v_slope = to_float(params1[4])
|
|
1328
|
+
self.side_slope = to_float(params1[5])
|
|
1329
|
+
self.ds_face_slope = to_float(params1[6])
|
|
1330
|
+
self.coriolis_coefficient = to_float(params1[7])
|
|
1331
|
+
self.bank_top_elevation = to_float(params1[8])
|
|
1350
1332
|
|
|
1351
1333
|
# Second parameter line
|
|
1352
1334
|
params2 = split_10_char(f"{block[3]:<20}")
|
|
1353
|
-
self.upstream_crest_height =
|
|
1354
|
-
self.downstream_crest_height =
|
|
1335
|
+
self.upstream_crest_height = to_float(params2[0])
|
|
1336
|
+
self.downstream_crest_height = to_float(params2[1])
|
|
1355
1337
|
|
|
1356
1338
|
def _write(self):
|
|
1357
1339
|
"""Function to write a valid FLAT-V WEIR block"""
|
|
1358
1340
|
|
|
1359
1341
|
_validate_unit(self)
|
|
1360
|
-
header =
|
|
1342
|
+
header = self._create_header()
|
|
1361
1343
|
labels = join_n_char_ljust(
|
|
1362
1344
|
self._label_len,
|
|
1363
1345
|
self.name,
|
|
@@ -1427,158 +1409,6 @@ class FLAT_V_WEIR(Unit): # noqa: N801
|
|
|
1427
1409
|
setattr(self, param, val)
|
|
1428
1410
|
|
|
1429
1411
|
|
|
1430
|
-
class RESERVOIR(Unit): # NOT CURRENTLY IN USE
|
|
1431
|
-
"""Class to hold and process RESERVOIR unit type
|
|
1432
|
-
|
|
1433
|
-
Args:
|
|
1434
|
-
name (str, optional): Unit name.
|
|
1435
|
-
comment (str, optional): Comment included in unit.
|
|
1436
|
-
all_labels (str, optional): Unlimited number of labels - not including first label (name).
|
|
1437
|
-
easting (float, optional): Easting coordinate of reservoir reference point (not used in computations).
|
|
1438
|
-
northing (float, optional): Northing coordinate of reservoir reference point (not used in computations).
|
|
1439
|
-
runoff_factor (float, optional): Rainfall runoff factor.
|
|
1440
|
-
num_pairs (float, optional): Number of elevation/area pairs.
|
|
1441
|
-
lat1 (str, optional): First lateral inflow label.
|
|
1442
|
-
lat2 (str, optional): Second lateral inflow label.
|
|
1443
|
-
lat3 (str, optional): Third lateral inflow label.
|
|
1444
|
-
lat4 (str, optional): Fourth lateral inflow label.
|
|
1445
|
-
data (pandas.DataFrame): Dataframe object containing all the reservoir section data.
|
|
1446
|
-
Columns are ``'Elevation','Plan Area'``
|
|
1447
|
-
|
|
1448
|
-
Returns:
|
|
1449
|
-
RESERVOIR: Flood Modeller RESERVOIR Unit class object"""
|
|
1450
|
-
|
|
1451
|
-
_unit = "RESERVOIR"
|
|
1452
|
-
|
|
1453
|
-
def _read(self, block):
|
|
1454
|
-
"""Function to read a given RESERVOIR WEIR block and store data as class attributes"""
|
|
1455
|
-
|
|
1456
|
-
# Extends label line to be correct length before splitting to pick up blank labels
|
|
1457
|
-
num_labels = len(block[1]) // self._label_len
|
|
1458
|
-
labels = split_n_char(f"{block[1]:<{num_labels*self._label_len}}", self._label_len)
|
|
1459
|
-
self.name = labels[0]
|
|
1460
|
-
self.all_labels = labels[0 : len(labels)]
|
|
1461
|
-
self.comment = block[0].replace("RESERVOIR", "").strip()
|
|
1462
|
-
|
|
1463
|
-
# Option 1 (runs if comment == "#revision#1")
|
|
1464
|
-
if self.comment == "#revision#1":
|
|
1465
|
-
# Lateral inflow labels
|
|
1466
|
-
lateral_labels = split_n_char(f"{block[2]:<{4*self._label_len}}", self._label_len)
|
|
1467
|
-
self.lat1 = lateral_labels[0]
|
|
1468
|
-
self.lat2 = lateral_labels[1]
|
|
1469
|
-
self.lat3 = lateral_labels[2]
|
|
1470
|
-
self.lat4 = lateral_labels[3]
|
|
1471
|
-
|
|
1472
|
-
# Number of pairs of data
|
|
1473
|
-
self.num_pairs = _to_int(block[3])
|
|
1474
|
-
|
|
1475
|
-
# Reservoir section data
|
|
1476
|
-
data_list = []
|
|
1477
|
-
for row in block[4 : len(block) - 1]:
|
|
1478
|
-
row_split = split_10_char(f"{row:<20}")
|
|
1479
|
-
elevation = _to_float(row_split[0]) # elevation
|
|
1480
|
-
plan_area = _to_float(row_split[1]) # plan area
|
|
1481
|
-
data_list.append([elevation, plan_area])
|
|
1482
|
-
reservoir_data = pd.DataFrame(data_list, columns=["Elevation", "Plan Area"])
|
|
1483
|
-
self.data = reservoir_data
|
|
1484
|
-
|
|
1485
|
-
# Coordinate data
|
|
1486
|
-
coordinate_data = split_n_char(
|
|
1487
|
-
f"{block[len(block)-1]:<{3*self._label_len}}",
|
|
1488
|
-
self._label_len,
|
|
1489
|
-
)
|
|
1490
|
-
self.easting = _to_float(coordinate_data[0])
|
|
1491
|
-
self.northing = _to_float(coordinate_data[1])
|
|
1492
|
-
self.runoff_factor = _to_float(coordinate_data[2])
|
|
1493
|
-
else: # Option 2 (runs if comment != "#revision#1")
|
|
1494
|
-
# Number of pairs of data
|
|
1495
|
-
self.num_pairs = _to_int(block[2])
|
|
1496
|
-
|
|
1497
|
-
# Reservoir section data
|
|
1498
|
-
data_list = []
|
|
1499
|
-
for row in block[3:]:
|
|
1500
|
-
row_split = split_10_char(f"{row:<20}")
|
|
1501
|
-
elevation = _to_float(row_split[0]) # elevation
|
|
1502
|
-
plan_area = _to_float(row_split[1]) # plan area
|
|
1503
|
-
data_list.append([elevation, plan_area])
|
|
1504
|
-
reservoir_data = pd.DataFrame(data_list, columns=["Elevation", "Plan Area"])
|
|
1505
|
-
self.data = reservoir_data
|
|
1506
|
-
|
|
1507
|
-
def _write(self):
|
|
1508
|
-
"""Function to write a valid RESERVOIR block"""
|
|
1509
|
-
|
|
1510
|
-
_validate_unit(self)
|
|
1511
|
-
header = "RESERVOIR " + self.comment
|
|
1512
|
-
self.labels = " ".join(self.all_labels)
|
|
1513
|
-
block = [header, self.labels]
|
|
1514
|
-
|
|
1515
|
-
# Option 1 (runs if comment == "#revision#1")
|
|
1516
|
-
if self.comment == "#revision#1":
|
|
1517
|
-
# Lateral inflow labels
|
|
1518
|
-
lat_labels = join_12_char_ljust(self.lat1, self.lat2, self.lat3, self.lat4)
|
|
1519
|
-
block.append(lat_labels)
|
|
1520
|
-
|
|
1521
|
-
# Number of pairs of data
|
|
1522
|
-
block.append(join_12_char_ljust(self.num_pairs))
|
|
1523
|
-
|
|
1524
|
-
# Reservoir section data
|
|
1525
|
-
section_data = [
|
|
1526
|
-
join_12_char_ljust(elevation, plan_area)
|
|
1527
|
-
for _, elevation, plan_area, in self.data.itertuples()
|
|
1528
|
-
]
|
|
1529
|
-
block.extend(section_data)
|
|
1530
|
-
|
|
1531
|
-
# Coordinate data
|
|
1532
|
-
coords = join_12_char_ljust(self.easting, self.northing, self.runoff_factor)
|
|
1533
|
-
block.append(coords)
|
|
1534
|
-
else: # Option 2 (runs if comment != "#revision#1")
|
|
1535
|
-
# Number of pairs of data
|
|
1536
|
-
block.append(join_12_char_ljust(self.num_pairs))
|
|
1537
|
-
|
|
1538
|
-
# Reservoir section data
|
|
1539
|
-
section_data = [
|
|
1540
|
-
join_12_char_ljust(elevation, plan_area)
|
|
1541
|
-
for _, elevation, plan_area, in self.data.itertuples()
|
|
1542
|
-
]
|
|
1543
|
-
block.extend(section_data)
|
|
1544
|
-
|
|
1545
|
-
return block
|
|
1546
|
-
|
|
1547
|
-
def _create_from_blank( # noqa: PLR0913
|
|
1548
|
-
self,
|
|
1549
|
-
name="new_reservoir",
|
|
1550
|
-
comment="",
|
|
1551
|
-
easting=0.0,
|
|
1552
|
-
northing=0.0,
|
|
1553
|
-
runoff_factor=0.0,
|
|
1554
|
-
num_pairs=1,
|
|
1555
|
-
data=None,
|
|
1556
|
-
lat1="",
|
|
1557
|
-
lat2="",
|
|
1558
|
-
lat3="",
|
|
1559
|
-
lat4="",
|
|
1560
|
-
):
|
|
1561
|
-
for param, val in {
|
|
1562
|
-
"name": name,
|
|
1563
|
-
"comment": comment,
|
|
1564
|
-
"easting": easting,
|
|
1565
|
-
"northing": northing,
|
|
1566
|
-
"runoff_factor": runoff_factor,
|
|
1567
|
-
"num_pairs": num_pairs,
|
|
1568
|
-
"lat1": lat1,
|
|
1569
|
-
"lat2": lat2,
|
|
1570
|
-
"lat3": lat3,
|
|
1571
|
-
"lat4": lat4,
|
|
1572
|
-
}.items():
|
|
1573
|
-
setattr(self, param, val)
|
|
1574
|
-
|
|
1575
|
-
self.data = (
|
|
1576
|
-
data
|
|
1577
|
-
if isinstance(data, pd.DataFrame)
|
|
1578
|
-
else pd.DataFrame([[0.0, 0.0]], columns=["Elevation", "Plan Area"])
|
|
1579
|
-
)
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
1412
|
class OUTFALL(Unit):
|
|
1583
1413
|
"""Class to hold and process OUTFALL unit type
|
|
1584
1414
|
|
|
@@ -1606,34 +1436,34 @@ class OUTFALL(Unit):
|
|
|
1606
1436
|
|
|
1607
1437
|
def _read(self, block):
|
|
1608
1438
|
"""Function to read a given OUTFALL block and store data as class attributes"""
|
|
1609
|
-
self._subtype = block[1]
|
|
1439
|
+
self._subtype = self._get_first_word(block[1])
|
|
1610
1440
|
self.flapped = self.subtype == "FLAPPED"
|
|
1611
1441
|
|
|
1612
1442
|
# Extends label line to be correct length before splitting to pick up blank labels
|
|
1613
1443
|
labels = split_n_char(f"{block[2]:<{2*self._label_len}}", self._label_len)
|
|
1614
1444
|
self.name = labels[0]
|
|
1615
1445
|
self.ds_label = labels[1]
|
|
1616
|
-
self.comment = block[0]
|
|
1446
|
+
self.comment = self._remove_unit_name(block[0])
|
|
1617
1447
|
|
|
1618
1448
|
# First parameter line
|
|
1619
1449
|
params1 = split_10_char(f"{block[3]:<60}")
|
|
1620
|
-
self.invert =
|
|
1621
|
-
self.soffit =
|
|
1622
|
-
self.bore_area =
|
|
1623
|
-
self.upstream_sill =
|
|
1624
|
-
self.downstream_sill =
|
|
1625
|
-
self.shape =
|
|
1450
|
+
self.invert = to_float(params1[0])
|
|
1451
|
+
self.soffit = to_float(params1[1])
|
|
1452
|
+
self.bore_area = to_float(params1[2])
|
|
1453
|
+
self.upstream_sill = to_float(params1[3])
|
|
1454
|
+
self.downstream_sill = to_float(params1[4])
|
|
1455
|
+
self.shape = to_str(params1[5], "RECTANGLE")
|
|
1626
1456
|
|
|
1627
1457
|
# Second parameter line
|
|
1628
1458
|
params2 = split_10_char(block[4])
|
|
1629
|
-
self.weir_flow =
|
|
1630
|
-
self.surcharged_flow =
|
|
1631
|
-
self.modular_limit =
|
|
1459
|
+
self.weir_flow = to_float(params2[0], 1.0)
|
|
1460
|
+
self.surcharged_flow = to_float(params2[1], 1.0)
|
|
1461
|
+
self.modular_limit = to_float(params2[2], 0.7)
|
|
1632
1462
|
|
|
1633
1463
|
def _write(self):
|
|
1634
1464
|
"""Function to write a valid OUTFALL block"""
|
|
1635
1465
|
_validate_unit(self) # Function to check the params are valid for CONDUIT unit
|
|
1636
|
-
header =
|
|
1466
|
+
header = self._create_header()
|
|
1637
1467
|
labels = join_n_char_ljust(self._label_len, self.name, self.ds_label)
|
|
1638
1468
|
|
|
1639
1469
|
self._subtype = "FLAPPED" if self.flapped else "OPEN"
|