floodmodeller-api 0.4.2__py3-none-any.whl → 0.4.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- floodmodeller_api/__init__.py +8 -9
- floodmodeller_api/_base.py +184 -176
- floodmodeller_api/backup.py +273 -273
- floodmodeller_api/dat.py +909 -838
- floodmodeller_api/diff.py +136 -119
- floodmodeller_api/ied.py +307 -311
- floodmodeller_api/ief.py +647 -646
- floodmodeller_api/ief_flags.py +253 -253
- floodmodeller_api/inp.py +266 -268
- floodmodeller_api/libs/libifcoremd.dll +0 -0
- floodmodeller_api/libs/libifcoremt.so.5 +0 -0
- floodmodeller_api/libs/libifport.so.5 +0 -0
- floodmodeller_api/{libmmd.dll → libs/libimf.so} +0 -0
- floodmodeller_api/libs/libintlc.so.5 +0 -0
- floodmodeller_api/libs/libmmd.dll +0 -0
- floodmodeller_api/libs/libsvml.so +0 -0
- floodmodeller_api/libs/libzzn_read.so +0 -0
- floodmodeller_api/libs/zzn_read.dll +0 -0
- floodmodeller_api/logs/__init__.py +2 -2
- floodmodeller_api/logs/lf.py +320 -314
- floodmodeller_api/logs/lf_helpers.py +354 -346
- floodmodeller_api/logs/lf_params.py +643 -529
- floodmodeller_api/mapping.py +84 -0
- floodmodeller_api/test/__init__.py +4 -4
- floodmodeller_api/test/conftest.py +9 -8
- floodmodeller_api/test/test_backup.py +117 -117
- floodmodeller_api/test/test_dat.py +221 -92
- floodmodeller_api/test/test_data/All Units 4_6.DAT +1081 -1081
- floodmodeller_api/test/test_data/All Units 4_6.feb +1081 -1081
- floodmodeller_api/test/test_data/BRIDGE.DAT +926 -926
- floodmodeller_api/test/test_data/Culvert_Inlet_Outlet.dat +36 -36
- floodmodeller_api/test/test_data/Culvert_Inlet_Outlet.feb +36 -36
- floodmodeller_api/test/test_data/DamBreakADI.xml +52 -52
- floodmodeller_api/test/test_data/DamBreakFAST.xml +58 -58
- floodmodeller_api/test/test_data/DamBreakFAST_dy.xml +53 -53
- floodmodeller_api/test/test_data/DamBreakTVD.xml +55 -55
- floodmodeller_api/test/test_data/DefenceBreach.xml +53 -53
- floodmodeller_api/test/test_data/DefenceBreachFAST.xml +60 -60
- floodmodeller_api/test/test_data/DefenceBreachFAST_dy.xml +55 -55
- floodmodeller_api/test/test_data/Domain1+2_QH.xml +76 -76
- floodmodeller_api/test/test_data/Domain1_H.xml +41 -41
- floodmodeller_api/test/test_data/Domain1_Q.xml +41 -41
- floodmodeller_api/test/test_data/Domain1_Q_FAST.xml +48 -48
- floodmodeller_api/test/test_data/Domain1_Q_FAST_dy.xml +48 -48
- floodmodeller_api/test/test_data/Domain1_Q_xml_expected.json +263 -0
- floodmodeller_api/test/test_data/Domain1_W.xml +41 -41
- floodmodeller_api/test/test_data/EX1.DAT +321 -321
- floodmodeller_api/test/test_data/EX1.ext +107 -107
- floodmodeller_api/test/test_data/EX1.feb +320 -320
- floodmodeller_api/test/test_data/EX1.gxy +107 -107
- floodmodeller_api/test/test_data/EX17.DAT +421 -422
- floodmodeller_api/test/test_data/EX17.ext +213 -213
- floodmodeller_api/test/test_data/EX17.feb +422 -422
- floodmodeller_api/test/test_data/EX18.DAT +375 -375
- floodmodeller_api/test/test_data/EX18_DAT_expected.json +3876 -0
- floodmodeller_api/test/test_data/EX2.DAT +302 -302
- floodmodeller_api/test/test_data/EX3.DAT +926 -926
- floodmodeller_api/test/test_data/EX3_DAT_expected.json +16235 -0
- floodmodeller_api/test/test_data/EX3_IEF_expected.json +61 -0
- floodmodeller_api/test/test_data/EX6.DAT +2084 -2084
- floodmodeller_api/test/test_data/EX6.ext +532 -532
- floodmodeller_api/test/test_data/EX6.feb +2084 -2084
- floodmodeller_api/test/test_data/EX6_DAT_expected.json +31647 -0
- floodmodeller_api/test/test_data/Event Data Example.DAT +336 -336
- floodmodeller_api/test/test_data/Event Data Example.ext +107 -107
- floodmodeller_api/test/test_data/Event Data Example.feb +336 -336
- floodmodeller_api/test/test_data/Linked1D2D.xml +52 -52
- floodmodeller_api/test/test_data/Linked1D2DFAST.xml +53 -53
- floodmodeller_api/test/test_data/Linked1D2DFAST_dy.xml +48 -48
- floodmodeller_api/test/test_data/Linked1D2D_xml_expected.json +313 -0
- floodmodeller_api/test/test_data/blockage.dat +50 -50
- floodmodeller_api/test/test_data/blockage.ext +45 -45
- floodmodeller_api/test/test_data/blockage.feb +9 -9
- floodmodeller_api/test/test_data/blockage.gxy +71 -71
- floodmodeller_api/test/test_data/defaultUnits.dat +127 -127
- floodmodeller_api/test/test_data/defaultUnits.ext +45 -45
- floodmodeller_api/test/test_data/defaultUnits.feb +9 -9
- floodmodeller_api/test/test_data/defaultUnits.fmpx +58 -58
- floodmodeller_api/test/test_data/defaultUnits.gxy +85 -85
- floodmodeller_api/test/test_data/ex3.ief +20 -20
- floodmodeller_api/test/test_data/ex3.lf1 +2800 -2800
- floodmodeller_api/test/test_data/ex4.DAT +1374 -1374
- floodmodeller_api/test/test_data/ex4_changed.DAT +1374 -1374
- floodmodeller_api/test/test_data/example1.inp +329 -329
- floodmodeller_api/test/test_data/example2.inp +158 -158
- floodmodeller_api/test/test_data/example3.inp +297 -297
- floodmodeller_api/test/test_data/example4.inp +388 -388
- floodmodeller_api/test/test_data/example5.inp +147 -147
- floodmodeller_api/test/test_data/example6.inp +154 -154
- floodmodeller_api/test/test_data/jump.dat +176 -176
- floodmodeller_api/test/test_data/network.dat +1374 -1374
- floodmodeller_api/test/test_data/network.ext +45 -45
- floodmodeller_api/test/test_data/network.exy +1 -1
- floodmodeller_api/test/test_data/network.feb +45 -45
- floodmodeller_api/test/test_data/network.ied +45 -45
- floodmodeller_api/test/test_data/network.ief +20 -20
- floodmodeller_api/test/test_data/network.inp +147 -147
- floodmodeller_api/test/test_data/network.pxy +57 -57
- floodmodeller_api/test/test_data/network.zzd +122 -122
- floodmodeller_api/test/test_data/network_dat_expected.json +21837 -0
- floodmodeller_api/test/test_data/network_from_tabularCSV.csv +87 -87
- floodmodeller_api/test/test_data/network_ied_expected.json +287 -0
- floodmodeller_api/test/test_data/rnweir.dat +9 -9
- floodmodeller_api/test/test_data/rnweir.ext +45 -45
- floodmodeller_api/test/test_data/rnweir.feb +9 -9
- floodmodeller_api/test/test_data/rnweir.gxy +45 -45
- floodmodeller_api/test/test_data/rnweir_default.dat +74 -74
- floodmodeller_api/test/test_data/rnweir_default.ext +45 -45
- floodmodeller_api/test/test_data/rnweir_default.feb +9 -9
- floodmodeller_api/test/test_data/rnweir_default.fmpx +58 -58
- floodmodeller_api/test/test_data/rnweir_default.gxy +53 -53
- floodmodeller_api/test/test_data/unit checks.dat +16 -16
- floodmodeller_api/test/test_ied.py +29 -29
- floodmodeller_api/test/test_ief.py +125 -24
- floodmodeller_api/test/test_inp.py +47 -48
- floodmodeller_api/test/test_json.py +114 -0
- floodmodeller_api/test/test_logs_lf.py +48 -51
- floodmodeller_api/test/test_tool.py +165 -154
- floodmodeller_api/test/test_toolbox_structure_log.py +234 -239
- floodmodeller_api/test/test_xml2d.py +151 -156
- floodmodeller_api/test/test_zzn.py +36 -34
- floodmodeller_api/to_from_json.py +218 -0
- floodmodeller_api/tool.py +332 -330
- floodmodeller_api/toolbox/__init__.py +5 -5
- floodmodeller_api/toolbox/example_tool.py +45 -45
- floodmodeller_api/toolbox/model_build/__init__.py +2 -2
- floodmodeller_api/toolbox/model_build/add_siltation_definition.py +100 -94
- floodmodeller_api/toolbox/model_build/structure_log/__init__.py +1 -1
- floodmodeller_api/toolbox/model_build/structure_log/structure_log.py +287 -289
- floodmodeller_api/toolbox/model_build/structure_log_definition.py +76 -72
- floodmodeller_api/units/__init__.py +10 -10
- floodmodeller_api/units/_base.py +214 -209
- floodmodeller_api/units/boundaries.py +467 -469
- floodmodeller_api/units/comment.py +52 -55
- floodmodeller_api/units/conduits.py +382 -403
- floodmodeller_api/units/helpers.py +123 -132
- floodmodeller_api/units/iic.py +107 -101
- floodmodeller_api/units/losses.py +305 -308
- floodmodeller_api/units/sections.py +444 -445
- floodmodeller_api/units/structures.py +1690 -1684
- floodmodeller_api/units/units.py +93 -102
- floodmodeller_api/units/unsupported.py +44 -44
- floodmodeller_api/units/variables.py +87 -89
- floodmodeller_api/urban1d/__init__.py +11 -11
- floodmodeller_api/urban1d/_base.py +188 -177
- floodmodeller_api/urban1d/conduits.py +93 -85
- floodmodeller_api/urban1d/general_parameters.py +58 -58
- floodmodeller_api/urban1d/junctions.py +81 -79
- floodmodeller_api/urban1d/losses.py +81 -74
- floodmodeller_api/urban1d/outfalls.py +114 -107
- floodmodeller_api/urban1d/raingauges.py +111 -108
- floodmodeller_api/urban1d/subsections.py +92 -93
- floodmodeller_api/urban1d/xsections.py +147 -141
- floodmodeller_api/util.py +77 -21
- floodmodeller_api/validation/parameters.py +660 -660
- floodmodeller_api/validation/urban_parameters.py +388 -404
- floodmodeller_api/validation/validation.py +110 -112
- floodmodeller_api/version.py +1 -1
- floodmodeller_api/xml2d.py +688 -684
- floodmodeller_api/xml2d_template.py +37 -37
- floodmodeller_api/zzn.py +387 -365
- {floodmodeller_api-0.4.2.dist-info → floodmodeller_api-0.4.3.dist-info}/LICENSE.txt +13 -13
- {floodmodeller_api-0.4.2.dist-info → floodmodeller_api-0.4.3.dist-info}/METADATA +82 -82
- floodmodeller_api-0.4.3.dist-info/RECORD +179 -0
- {floodmodeller_api-0.4.2.dist-info → floodmodeller_api-0.4.3.dist-info}/WHEEL +1 -1
- floodmodeller_api-0.4.3.dist-info/entry_points.txt +3 -0
- floodmodeller_api/libifcoremd.dll +0 -0
- floodmodeller_api/test/test_data/EX3.bmp +0 -0
- floodmodeller_api/test/test_data/test_output.csv +0 -87
- floodmodeller_api/zzn_read.dll +0 -0
- floodmodeller_api-0.4.2.data/scripts/fmapi-add_siltation.bat +0 -2
- floodmodeller_api-0.4.2.data/scripts/fmapi-add_siltation.py +0 -3
- floodmodeller_api-0.4.2.data/scripts/fmapi-structure_log.bat +0 -2
- floodmodeller_api-0.4.2.data/scripts/fmapi-structure_log.py +0 -3
- floodmodeller_api-0.4.2.data/scripts/fmapi-toolbox.bat +0 -2
- floodmodeller_api-0.4.2.data/scripts/fmapi-toolbox.py +0 -41
- floodmodeller_api-0.4.2.dist-info/RECORD +0 -169
- {floodmodeller_api-0.4.2.dist-info → floodmodeller_api-0.4.3.dist-info}/top_level.txt +0 -0
|
@@ -1,1684 +1,1690 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Flood Modeller Python API
|
|
3
|
-
Copyright (C)
|
|
4
|
-
|
|
5
|
-
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
|
|
6
|
-
as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
7
|
-
|
|
8
|
-
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
9
|
-
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
10
|
-
|
|
11
|
-
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
|
|
12
|
-
|
|
13
|
-
If you have any query about this program or this License, please contact us at support@floodmodeller.com or write to the following
|
|
14
|
-
address: Jacobs UK Limited, Flood Modeller, Cottons Centre, Cottons Lane, London, SE1 2QG, United Kingdom.
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
from .
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
self.
|
|
134
|
-
self.
|
|
135
|
-
self.
|
|
136
|
-
self.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
self.
|
|
144
|
-
self.
|
|
145
|
-
self.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
self.
|
|
152
|
-
self.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
# Read bridge opening data
|
|
170
|
-
self.opening_nrows = int(split_10_char(br_block[6 + self.section_nrows])[0])
|
|
171
|
-
data_list = []
|
|
172
|
-
for row in br_block[6 + self.section_nrows + 1 :]:
|
|
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
|
-
)
|
|
183
|
-
|
|
184
|
-
# Read USBPR type unit
|
|
185
|
-
elif self.subtype == "USBPR1978":
|
|
186
|
-
# Read Params
|
|
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)
|
|
200
|
-
|
|
201
|
-
self.abutment_type = split_10_char(br_block[5])[0]
|
|
202
|
-
self.abutment_alignment = split_10_char(br_block[7])[0]
|
|
203
|
-
|
|
204
|
-
pier_info = split_10_char(f"{br_block[6]:<40}")
|
|
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
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
"
|
|
271
|
-
"
|
|
272
|
-
"
|
|
273
|
-
"Cd Full",
|
|
274
|
-
"
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
self.
|
|
289
|
-
self.
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
self.
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
data_list
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
self.
|
|
358
|
-
self.
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
self.
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
self.
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
br_block.
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
self.
|
|
405
|
-
self.
|
|
406
|
-
|
|
407
|
-
self.
|
|
408
|
-
self.
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
f"{str(self.
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
br_block.
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
br_block.
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
self.
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
br_block.
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
br_block.
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
return
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
self.
|
|
602
|
-
self.
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
self.
|
|
609
|
-
self.
|
|
610
|
-
self.
|
|
611
|
-
self.
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
self.
|
|
621
|
-
self.
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
self.
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
"
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
"
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
self.
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
self.
|
|
657
|
-
self.
|
|
658
|
-
self.
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
self.
|
|
678
|
-
self.
|
|
679
|
-
self.
|
|
680
|
-
self.
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
self.
|
|
691
|
-
self.
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
params2 += join_10_char(
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
self.modular_limits["
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
self.modular_limits["
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
block.append(f"{
|
|
726
|
-
|
|
727
|
-
block.
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
self.
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
block.append(f"{
|
|
745
|
-
|
|
746
|
-
block.
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
gate_data =
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
self.
|
|
845
|
-
self.
|
|
846
|
-
self.
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
self.
|
|
869
|
-
self.
|
|
870
|
-
self.
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
"
|
|
901
|
-
"
|
|
902
|
-
"
|
|
903
|
-
"
|
|
904
|
-
"
|
|
905
|
-
"
|
|
906
|
-
"
|
|
907
|
-
"
|
|
908
|
-
"
|
|
909
|
-
"
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
"
|
|
992
|
-
"
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
self.
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
self.
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
self.
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
self.
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
self.
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
block.append(
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
"
|
|
1095
|
-
"
|
|
1096
|
-
"
|
|
1097
|
-
"
|
|
1098
|
-
"
|
|
1099
|
-
"
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
self.
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
self.
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
self.
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
block
|
|
1153
|
-
|
|
1154
|
-
#
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
self.
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
"
|
|
1185
|
-
"
|
|
1186
|
-
"
|
|
1187
|
-
"
|
|
1188
|
-
"
|
|
1189
|
-
"
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
self.
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
self.
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
self.
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
self.
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
block.append(
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
"
|
|
1287
|
-
"
|
|
1288
|
-
"
|
|
1289
|
-
"
|
|
1290
|
-
"
|
|
1291
|
-
"
|
|
1292
|
-
"
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
self.
|
|
1337
|
-
self.
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
self.
|
|
1342
|
-
self.
|
|
1343
|
-
self.
|
|
1344
|
-
self.
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
self.
|
|
1349
|
-
self.
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
self.
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
self.
|
|
1372
|
-
self.
|
|
1373
|
-
self.
|
|
1374
|
-
self.
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
"
|
|
1411
|
-
"
|
|
1412
|
-
"
|
|
1413
|
-
"
|
|
1414
|
-
"
|
|
1415
|
-
"
|
|
1416
|
-
"
|
|
1417
|
-
"
|
|
1418
|
-
"
|
|
1419
|
-
"
|
|
1420
|
-
"
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
self.
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
"
|
|
1563
|
-
"
|
|
1564
|
-
"
|
|
1565
|
-
"
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
self.
|
|
1610
|
-
self.
|
|
1611
|
-
|
|
1612
|
-
#
|
|
1613
|
-
|
|
1614
|
-
self.
|
|
1615
|
-
self.
|
|
1616
|
-
self.
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
self.
|
|
1624
|
-
self.
|
|
1625
|
-
self.
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
"
|
|
1677
|
-
"
|
|
1678
|
-
"
|
|
1679
|
-
"
|
|
1680
|
-
"
|
|
1681
|
-
"
|
|
1682
|
-
"
|
|
1683
|
-
|
|
1684
|
-
|
|
1
|
+
"""
|
|
2
|
+
Flood Modeller Python API
|
|
3
|
+
Copyright (C) 2024 Jacobs U.K. Limited
|
|
4
|
+
|
|
5
|
+
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
|
|
6
|
+
as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
7
|
+
|
|
8
|
+
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
9
|
+
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
10
|
+
|
|
11
|
+
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
|
|
12
|
+
|
|
13
|
+
If you have any query about this program or this License, please contact us at support@floodmodeller.com or write to the following
|
|
14
|
+
address: Jacobs UK Limited, Flood Modeller, Cottons Centre, Cottons Lane, London, SE1 2QG, United Kingdom.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import pandas as pd
|
|
18
|
+
|
|
19
|
+
from floodmodeller_api.validation import _validate_unit
|
|
20
|
+
|
|
21
|
+
from ._base import Unit
|
|
22
|
+
from .helpers import (
|
|
23
|
+
_to_float,
|
|
24
|
+
_to_int,
|
|
25
|
+
_to_str,
|
|
26
|
+
join_10_char,
|
|
27
|
+
join_12_char_ljust,
|
|
28
|
+
join_n_char_ljust,
|
|
29
|
+
split_10_char,
|
|
30
|
+
split_n_char,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class BRIDGE(Unit):
|
|
35
|
+
"""Class to hold and process BRIDGE unit type. The Bridge class supports the three main bridge sub-types in
|
|
36
|
+
Flood Modeller: Arch, USBPR1978 and Pierloss. Each of these sub-types forms a unique instance of the class
|
|
37
|
+
which is differentiated by the `BRIDGE.subtype` attribute. All bridge types have the same common attributes:
|
|
38
|
+
|
|
39
|
+
**Common Attributes**
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
name (str): Bridge section name
|
|
43
|
+
comment (str): Comment included in unit
|
|
44
|
+
ds_label (str): Downstream label
|
|
45
|
+
us_remote_label, ds_remote_label (str): Remote labels
|
|
46
|
+
subtype (str): Defines the type of bridge unit (*Should not be changed*)
|
|
47
|
+
|
|
48
|
+
**ARCH Type (``BRIDGE.subtype == 'ARCH'``)**
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
calibration_coefficient (float): Calibration coefficient
|
|
52
|
+
skew (float): Bridge skew
|
|
53
|
+
bridge_width_dual (float): If modelled as dual bridge, the distance between upstream and downstream face of
|
|
54
|
+
bridge (0.00 if not modelling as dual bridge):
|
|
55
|
+
bridge_dist_dual (float): If modelled as dual bridge, the total distance between upstream and downstream
|
|
56
|
+
faces of both bridges (0.00 if not modelling as dual bridge):
|
|
57
|
+
orifice_flow (bool): Whether or not to model surcharged bridge as orifice flow
|
|
58
|
+
orifice_lower_transition_dist, orifice_upper_transition_dist (float): Upper and lower transition distances
|
|
59
|
+
for when using orifice flow
|
|
60
|
+
orifice_discharge_coefficient (float): Orifice discharge coefficient for when using orifice flow
|
|
61
|
+
section_data (pandas.DataFrame): Dataframe object representing the cross section. Columns are ``'X'``, ``'Y'``,
|
|
62
|
+
``'Mannings n'`` and ``'Embankments'``
|
|
63
|
+
opening_data (pandas.DataFrame): Dataframe object representing the openings in the bridge. Columns are
|
|
64
|
+
``'Start'``, ``'Finish'``, ``'Springing Level'`` and ``'Soffit Level'``
|
|
65
|
+
|
|
66
|
+
**USBPR Type (``BRIDGE.subtype == 'USBPR1978'``)**
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
calibration_coefficient (float): Calibration coefficient
|
|
70
|
+
skew (float): Bridge skew
|
|
71
|
+
bridge_width_dual (float): If modelled as dual bridge, the distance between upstream and downstream face of bridge
|
|
72
|
+
(0.00 if not modelling as dual bridge)
|
|
73
|
+
bridge_dist_dual (float): If modelled as dual bridge, the total distance between upstream and downstream faces of
|
|
74
|
+
both bridges (0.00 if not modelling as dual bridge)
|
|
75
|
+
orifice_flow (bool): Whether or not to model surcharged bridge as orifice flow
|
|
76
|
+
orifice_lower_transition_dist, orifice_upper_transition_dist (float): Transition distances for when using orifice flow
|
|
77
|
+
orifice_discharge_coefficient (float): Orifice discharge coefficient for when using orifice flow
|
|
78
|
+
abutment_type (str): Type of abutment: ``'3'`` (default), ``'2'`` (30-degree wing wall abutment), ``'1'`` (span between
|
|
79
|
+
abutments < 60 metres and either 90-degree wing or vertical wall abutment)
|
|
80
|
+
abutment_alignment (str): Abutment alignment to normal direction of flow: ``'ALIGNED'`` or ``'SKEW'``
|
|
81
|
+
specify_piers (bool): Whether or not to explicity model piers
|
|
82
|
+
total_pier_width (float): Total width of all piers at right ange to flow direction, only used if ``specify_piers == True``
|
|
83
|
+
npiers (int): Total number of piers in direction of flow, only used if ``specify_piers == True``
|
|
84
|
+
pier_use_calibration_coeff (bool): Whether to use a calibration coefficient to model piers. If set to False it would use
|
|
85
|
+
the pier shape.
|
|
86
|
+
pier_calibration_coeff (float): Calibration coefficient for modelling piers, only used if
|
|
87
|
+
``specify_piers == True AND pier_use_calibration_coeff == True``
|
|
88
|
+
pier_shape (str): Cross-sectional pier shape with options: ``'RECTANGLE'``, ``'CYLINDER'``, ``'SQUARE'``, ``'I-BEAM'``.
|
|
89
|
+
Only used if ``specify_piers == True AND pier_use_calibration_coeff == False``
|
|
90
|
+
pier_faces (str): Shape of pier faces with options: ``'STREAMLINE'``, ``'SEMICIRCLE'``, ``'TRIANGLE'``, ``'DIAPHRAGM'``.
|
|
91
|
+
Only used if ``specify_piers == True AND pier_use_calibration_coeff == False``
|
|
92
|
+
soffit_shape (str): Shape of soffit (``'FLAT'`` or ``'ARCH'``), only used if ``specify_piers == False``
|
|
93
|
+
section_data (pandas.Dataframe): Dataframe object representing the cross section. Columns are ``'X'``, ``'Y'``, ``'Mannings n'``
|
|
94
|
+
and ``'Embankments'``
|
|
95
|
+
opening_data (pandas.Dataframe): Dataframe object representing the openings in the bridge. Columns are ``'Start'``, ``'Finish'``,
|
|
96
|
+
``'Springing Level'`` and ``'Soffit Level'``
|
|
97
|
+
culvert_data (pandas.Dataframe): Dataframe object representing any flood relief culverts in the bridge. Columns are ``'Invert'``,
|
|
98
|
+
``'Soffit'``, ``'Section Area'``, ``'Cd Part Full'``, ``'Cd Full'`` and ``'Drowning Coefficient'``
|
|
99
|
+
|
|
100
|
+
**PIERLOSS Type (``BRIDGE.subtype == 'PIERLOSS'``)**
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
calibration_coefficient (float): Calibration coefficient
|
|
104
|
+
orifice_flow (bool): Whether or not to model surcharged bridge as orifice flow
|
|
105
|
+
orifice_lower_transition_dist, orifice_upper_transition_dist (float): Transition distances for when using orifice flow
|
|
106
|
+
orifice_discharge_coefficient (float): Orifice discharge coefficient for when using orifice flow
|
|
107
|
+
pier_coefficient (float): Pier coefficient
|
|
108
|
+
bridge_width (float): Distance in direction of flow from U/S to D/S cross section of bridge (for reference only)
|
|
109
|
+
us_section_data (pandas.Dataframe): Dataframe object representing the upstream cross section. Columns are ``'X'``, ``'Y'``,
|
|
110
|
+
``'Mannings n'``, ``'Embankments'`` and ``'Top Level'``
|
|
111
|
+
ds_section_data (pandas.Dataframe): Dataframe object representing the downstream cross section, if no downstream section is
|
|
112
|
+
specified this will be an empty dataframe. Columns are ``'X'``, ``'Y'``, ``'Mannings n'``, ``'Embankments'`` and ``'Top Level'``
|
|
113
|
+
pier_locs_data (pandas.Dataframe): Dataframe object representing the pier locations. Columns are ``'Left X'``, ``'Left Top Level'``,
|
|
114
|
+
``'Right X'``, ``'Right Top Level'``
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
Raises:
|
|
118
|
+
NotImplementedError: Raised if class is initialised without existing Bridge block (i.e. if attempting to create new Bridge unit).
|
|
119
|
+
This will be an option for future releases
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
BRIDGE: Flood Modeller BRIDGE Unit class object
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
_unit = "BRIDGE"
|
|
126
|
+
|
|
127
|
+
def _read(self, br_block): # noqa: C901, PLR0912, PLR0915
|
|
128
|
+
"""Function to read a given BRIDGE block and store data as class attributes"""
|
|
129
|
+
self._subtype = br_block[1].split(" ")[0].strip()
|
|
130
|
+
# Extends label line to be correct length before splitting to pick up blank labels
|
|
131
|
+
labels = split_n_char(f"{br_block[2]:<{4*self._label_len}}", self._label_len)
|
|
132
|
+
self.name = labels[0]
|
|
133
|
+
self.ds_label = labels[1]
|
|
134
|
+
self.us_remote_label = labels[2]
|
|
135
|
+
self.ds_remote_label = labels[3]
|
|
136
|
+
self.comment = br_block[0].replace("BRIDGE", "").strip()
|
|
137
|
+
|
|
138
|
+
# Read ARCH type unit
|
|
139
|
+
if self.subtype == "ARCH":
|
|
140
|
+
# Read Params
|
|
141
|
+
params = split_10_char(f"{br_block[4]:<90}")
|
|
142
|
+
self.calibration_coefficient = _to_float(params[0], 1.0)
|
|
143
|
+
self.skew = _to_float(params[1])
|
|
144
|
+
self.bridge_width_dual = _to_float(params[2])
|
|
145
|
+
self.bridge_dist_dual = _to_float(params[3])
|
|
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"],
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
# Read bridge opening data
|
|
170
|
+
self.opening_nrows = int(split_10_char(br_block[6 + self.section_nrows])[0])
|
|
171
|
+
data_list = []
|
|
172
|
+
for row in br_block[6 + self.section_nrows + 1 :]:
|
|
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
|
+
)
|
|
183
|
+
|
|
184
|
+
# Read USBPR type unit
|
|
185
|
+
elif self.subtype == "USBPR1978":
|
|
186
|
+
# Read Params
|
|
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)
|
|
200
|
+
|
|
201
|
+
self.abutment_type = split_10_char(br_block[5])[0]
|
|
202
|
+
self.abutment_alignment = split_10_char(br_block[7])[0]
|
|
203
|
+
|
|
204
|
+
pier_info = split_10_char(f"{br_block[6]:<40}")
|
|
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
|
+
)
|
|
233
|
+
|
|
234
|
+
# Read bridge opening data
|
|
235
|
+
self.opening_nrows = int(split_10_char(br_block[9 + self.section_nrows])[0])
|
|
236
|
+
data_list = []
|
|
237
|
+
start_row = 9 + self.section_nrows + 1
|
|
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"],
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
# Read flood relief culvert data
|
|
252
|
+
self.culvert_nrows = int(
|
|
253
|
+
split_10_char(br_block[9 + self.section_nrows + self.opening_nrows + 1])[0],
|
|
254
|
+
)
|
|
255
|
+
data_list = []
|
|
256
|
+
start_row = 9 + self.section_nrows + self.opening_nrows + 2
|
|
257
|
+
end_row = start_row + self.culvert_nrows
|
|
258
|
+
for row in br_block[start_row:end_row]:
|
|
259
|
+
row_split = split_10_char(f"{row:<60}")
|
|
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
|
+
],
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
# Read Pierloss type bridge
|
|
280
|
+
elif self.subtype == "PIERLOSS":
|
|
281
|
+
# Read Params
|
|
282
|
+
params = split_10_char(f"{br_block[4]:<50}")
|
|
283
|
+
self.calibration_coefficient = _to_float(params[0], 1.0)
|
|
284
|
+
if params[1] == "ORIFICE":
|
|
285
|
+
self.orifice_flow = True
|
|
286
|
+
else:
|
|
287
|
+
self.orifice_flow = False
|
|
288
|
+
self.orifice_lower_transition_dist = _to_float(params[3])
|
|
289
|
+
self.orifice_upper_transition_dist = _to_float(params[4])
|
|
290
|
+
self.orifice_discharge_coefficient = _to_float(params[2], 1.0)
|
|
291
|
+
additional_params = split_10_char(f"{br_block[5]:<20}")
|
|
292
|
+
self.pier_coefficient = _to_float(additional_params[0], 0.9)
|
|
293
|
+
self.bridge_width = _to_float(additional_params[1])
|
|
294
|
+
|
|
295
|
+
# Read US cross section data
|
|
296
|
+
self.us_section_nrows = int(split_10_char(br_block[6])[0])
|
|
297
|
+
data_list = []
|
|
298
|
+
for row in br_block[7 : 7 + self.us_section_nrows]:
|
|
299
|
+
row_split = split_10_char(f"{row:<60}")
|
|
300
|
+
x = _to_float(row_split[0]) # chainage
|
|
301
|
+
y = _to_float(row_split[1]) # elevation
|
|
302
|
+
n = _to_float(row_split[2]) # Mannings
|
|
303
|
+
embankment = row_split[4] # Embankment flag
|
|
304
|
+
top_level = row_split[5] # Top Level (m)
|
|
305
|
+
data_list.append([x, y, n, embankment, top_level])
|
|
306
|
+
self.us_section_data = pd.DataFrame(
|
|
307
|
+
data_list,
|
|
308
|
+
columns=["X", "Y", "Mannings n", "Embankments", "Top Level"],
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
# Read DS cross section data
|
|
312
|
+
new_idx = 6 + 1 + self.us_section_nrows
|
|
313
|
+
self.ds_section_nrows = int(split_10_char(br_block[new_idx])[0])
|
|
314
|
+
data_list = []
|
|
315
|
+
for row in br_block[new_idx + 1 : new_idx + 1 + self.ds_section_nrows]:
|
|
316
|
+
row_split = split_10_char(f"{row:<60}")
|
|
317
|
+
x = _to_float(row_split[0]) # chainage
|
|
318
|
+
y = _to_float(row_split[1]) # elevation
|
|
319
|
+
n = _to_float(row_split[2]) # Mannings
|
|
320
|
+
embankment = row_split[4] # Embankment flag
|
|
321
|
+
top_level = row_split[5] # Top Level (m)
|
|
322
|
+
data_list.append([x, y, n, embankment, top_level])
|
|
323
|
+
self.ds_section_data = pd.DataFrame(
|
|
324
|
+
data_list,
|
|
325
|
+
columns=["X", "Y", "Mannings n", "Embankments", "Top Level"],
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
# Read pier locations
|
|
329
|
+
new_idx += 1 + self.ds_section_nrows
|
|
330
|
+
self.pier_locs_nrows = int(split_10_char(br_block[new_idx])[0])
|
|
331
|
+
data_list = []
|
|
332
|
+
for row in br_block[new_idx + 1 : new_idx + 1 + self.pier_locs_nrows]:
|
|
333
|
+
row_split = split_10_char(f"{row:<40}")
|
|
334
|
+
l_x = _to_float(row_split[0]) # chainage
|
|
335
|
+
l_top_level = _to_float(row_split[1]) # Top Level (m)
|
|
336
|
+
r_x = _to_float(row_split[2]) # chainage
|
|
337
|
+
r_top_level = _to_float(row_split[3]) # Top Level (m)
|
|
338
|
+
data_list.append([l_x, l_top_level, r_x, r_top_level])
|
|
339
|
+
self.pier_locs_data = pd.DataFrame(
|
|
340
|
+
data_list,
|
|
341
|
+
columns=["Left X", "Left Top Level", "Right X", "Right Top Level"],
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
else:
|
|
345
|
+
# This else block is triggered for bridge subtypes which aren't yet supported, and just keeps the 'br_block' in it's raw state to write back.
|
|
346
|
+
print(
|
|
347
|
+
f'This Bridge sub-type: "{self.subtype}" is currently unsupported for reading/editing',
|
|
348
|
+
)
|
|
349
|
+
self._raw_block = br_block
|
|
350
|
+
self.name = br_block[2][:12].strip()
|
|
351
|
+
|
|
352
|
+
def _write(self): # noqa: C901, PLR0912, PLR0915
|
|
353
|
+
"""Function to write a valid BRIDGE block"""
|
|
354
|
+
_validate_unit(self) # Function to check the params are valid for BRIDGE unit
|
|
355
|
+
header = "BRIDGE " + self.comment
|
|
356
|
+
labels = join_n_char_ljust(
|
|
357
|
+
self._label_len,
|
|
358
|
+
self.name,
|
|
359
|
+
self.ds_label,
|
|
360
|
+
self.us_remote_label,
|
|
361
|
+
self.ds_remote_label,
|
|
362
|
+
)
|
|
363
|
+
br_block = [header, self.subtype, labels]
|
|
364
|
+
|
|
365
|
+
if self.subtype == "ARCH":
|
|
366
|
+
orifice = "ORIFICE" if self.orifice_flow else ""
|
|
367
|
+
params = join_10_char(
|
|
368
|
+
self.calibration_coefficient,
|
|
369
|
+
self.skew,
|
|
370
|
+
self.bridge_width_dual,
|
|
371
|
+
self.bridge_dist_dual,
|
|
372
|
+
"",
|
|
373
|
+
orifice,
|
|
374
|
+
self.orifice_lower_transition_dist,
|
|
375
|
+
self.orifice_upper_transition_dist,
|
|
376
|
+
self.orifice_discharge_coefficient,
|
|
377
|
+
)
|
|
378
|
+
self.section_nrows = len(self.section_data)
|
|
379
|
+
br_block.extend(["MANNING", params, f"{str(self.section_nrows):>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)
|
|
387
|
+
|
|
388
|
+
br_block.extend(section_data)
|
|
389
|
+
|
|
390
|
+
self.opening_nrows = len(self.opening_data)
|
|
391
|
+
br_block.append(f"{str(self.opening_nrows):>10}")
|
|
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
|
+
|
|
397
|
+
br_block.extend(opening_data)
|
|
398
|
+
|
|
399
|
+
return br_block
|
|
400
|
+
|
|
401
|
+
if self.subtype == "USBPR1978":
|
|
402
|
+
orifice = "ORIFICE" if self.orifice_flow else ""
|
|
403
|
+
params = join_10_char(
|
|
404
|
+
self.calibration_coefficient,
|
|
405
|
+
self.skew,
|
|
406
|
+
self.bridge_width_dual,
|
|
407
|
+
self.bridge_dist_dual,
|
|
408
|
+
self.total_pier_width,
|
|
409
|
+
orifice,
|
|
410
|
+
self.orifice_lower_transition_dist,
|
|
411
|
+
self.orifice_upper_transition_dist,
|
|
412
|
+
self.orifice_discharge_coefficient,
|
|
413
|
+
)
|
|
414
|
+
if self.specify_piers:
|
|
415
|
+
if self.pier_use_calibration_coeff:
|
|
416
|
+
pier_params = f'{self.npiers:>10}{"COEF":<10}{"":>10}{self.calibration_coefficient:>10.3f}'
|
|
417
|
+
else:
|
|
418
|
+
pier_params = f"{self.npiers:>10}{self.pier_shape:<10}{self.pier_faces:<10}"
|
|
419
|
+
else:
|
|
420
|
+
pier_params = f"{0:>10}{self.soffit_shape}"
|
|
421
|
+
|
|
422
|
+
self.section_nrows = len(self.section_data)
|
|
423
|
+
br_block.extend(
|
|
424
|
+
[
|
|
425
|
+
"MANNING",
|
|
426
|
+
params,
|
|
427
|
+
f"{str(self.abutment_type):>10}",
|
|
428
|
+
pier_params,
|
|
429
|
+
self.abutment_alignment,
|
|
430
|
+
f"{str(self.section_nrows):>10}",
|
|
431
|
+
],
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
section_data = []
|
|
435
|
+
for _, x, y, n, embankments in self.section_data.itertuples():
|
|
436
|
+
# Adding extra 10 spaces before embankment flag
|
|
437
|
+
row = join_10_char(x, y, n, "")
|
|
438
|
+
row += embankments
|
|
439
|
+
section_data.append(row)
|
|
440
|
+
br_block.extend(section_data)
|
|
441
|
+
|
|
442
|
+
self.opening_nrows = len(self.opening_data)
|
|
443
|
+
br_block.append(f"{str(self.opening_nrows):>10}")
|
|
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)
|
|
448
|
+
br_block.extend(opening_data)
|
|
449
|
+
|
|
450
|
+
self.culvert_nrows = len(self.culvert_data)
|
|
451
|
+
br_block.append(f"{str(self.culvert_nrows):>10}")
|
|
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)
|
|
464
|
+
br_block.extend(culvert_data)
|
|
465
|
+
|
|
466
|
+
return br_block
|
|
467
|
+
|
|
468
|
+
if self.subtype == "PIERLOSS":
|
|
469
|
+
orifice = "ORIFICE" if self.orifice_flow else ""
|
|
470
|
+
params = join_10_char(
|
|
471
|
+
self.calibration_coefficient,
|
|
472
|
+
orifice,
|
|
473
|
+
self.orifice_discharge_coefficient,
|
|
474
|
+
self.orifice_lower_transition_dist,
|
|
475
|
+
self.orifice_upper_transition_dist,
|
|
476
|
+
)
|
|
477
|
+
additional_params = join_10_char(self.pier_coefficient, self.bridge_width)
|
|
478
|
+
self.us_section_nrows = len(self.us_section_data)
|
|
479
|
+
br_block.extend(
|
|
480
|
+
[
|
|
481
|
+
"YARNELL",
|
|
482
|
+
params,
|
|
483
|
+
additional_params,
|
|
484
|
+
f"{str(self.us_section_nrows):>10}",
|
|
485
|
+
],
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
us_section_data = []
|
|
489
|
+
for _, x, y, n, embankments, top_level in self.us_section_data.itertuples():
|
|
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)
|
|
495
|
+
br_block.extend(us_section_data)
|
|
496
|
+
|
|
497
|
+
self.ds_section_nrows = len(self.ds_section_data)
|
|
498
|
+
br_block.append(f"{str(self.ds_section_nrows):>10}")
|
|
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)
|
|
506
|
+
br_block.extend(ds_section_data)
|
|
507
|
+
|
|
508
|
+
self.pier_locs_nrows = len(self.pier_locs_data)
|
|
509
|
+
br_block.append(f"{str(self.pier_locs_nrows):>10}")
|
|
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)
|
|
520
|
+
br_block.extend(pier_locs_data)
|
|
521
|
+
|
|
522
|
+
return br_block
|
|
523
|
+
|
|
524
|
+
return self._raw_block
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
class SLUICE(Unit):
|
|
528
|
+
"""The Sluice class supports two sluice sub-types in Flood Modeller: RADIAL and VERTICAL. Each of these sub-types forms
|
|
529
|
+
a unique instance of the class which is differentiated by the `SLUICE.subtype` attribute. There are also several different
|
|
530
|
+
attributes depending on the `.control_method` used. All sluice types have the same common attributes:
|
|
531
|
+
|
|
532
|
+
**Common Attributes**
|
|
533
|
+
|
|
534
|
+
Args:
|
|
535
|
+
name (str): Sluice section name (upstream label)
|
|
536
|
+
ds_label (str): Downstream label
|
|
537
|
+
remote_label (str): Remote label
|
|
538
|
+
comment (str): Comment included in unit
|
|
539
|
+
subtype (str): Defines the type of sluice unit (*Should not be changed*)
|
|
540
|
+
weir_flow_coefficient (float): Coefficient of approach velocity for weir flow (0.4 - 3.0)
|
|
541
|
+
under_gate_flow (float): Coefficient of approach velocity for under gate flow
|
|
542
|
+
over_gate_flow (float): Coefficient of approach velocity for over gate flow
|
|
543
|
+
weir_breadth (float): breadth of weir (for single gate) perpendicular to flow direction
|
|
544
|
+
crest_elevation (float): Elevation of weir crest
|
|
545
|
+
gate_height_or_chord (float): Height of sluice gate (m) (if sluice subtype is VERTICAL or subtype is RADIAL and
|
|
546
|
+
``use_degrees == False``). OR the cord made by the arc of sluice gate (m) if subtype is RADIAL and
|
|
547
|
+
``use_degrees == True``.
|
|
548
|
+
weir_length (float): Length of weir (m) in flow direction
|
|
549
|
+
us_weir_height (float): Vertical distance from weir crest to upstream bed level
|
|
550
|
+
ds_weir_height (float): Vertical distance from weir crest to downstream bed level
|
|
551
|
+
bias_factor (float): Only used when control_method set to 'REMOTE WATER LEVEL'
|
|
552
|
+
modular_limits (dict): Dictionary of modular limit values. Keys: {'weir_flow', 'under_gate_flow', 'over_gate_flow'}. If they
|
|
553
|
+
are all set equal to zero, then a variable calculation method is used.
|
|
554
|
+
ngates (int): number of gates
|
|
555
|
+
timeunit (str): Unit of time, e.g. 'HOURS', 'MINUTES' or 'SECONDS'. See Flood Modeller documentation for all available options.
|
|
556
|
+
extendmethod (str): Data extending method: 'EXTEND', 'NOEXTEND' or 'REPEAT'.
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
**Attributes used when ``SLUICE.control_method == 'TIME'``**
|
|
560
|
+
|
|
561
|
+
Args:
|
|
562
|
+
gates (List[pandas.Series]): List of Data series representing the gate control with 'Time' index and 'Gate Opening' (m) as the data
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
**Attributes used when ``SLUICE.control_method == 'LOGICAL'``**
|
|
566
|
+
|
|
567
|
+
Args:
|
|
568
|
+
gates (List[pandas.DataFrame]): List of Dataframes representing the gate control with 'Time' as index and 'Mode' and 'Gate Opening' (m) as the columns.
|
|
569
|
+
The Mode is set to 'AUTO', 'MANUAL' or [blank] depending on the control mode at that time.
|
|
570
|
+
max_movement_rate (float): Maximum movement rate of the structure
|
|
571
|
+
max_setting (float): Maximum setting of the structure
|
|
572
|
+
min_setting (float): Minimum setting of the structure
|
|
573
|
+
rules (List[dict]): List of logical rules to use. Each rule is represented as a Dictionary with keys 'name' and 'logic'.
|
|
574
|
+
time_rule_data (pandas.Series): Series containing data on which operating rules to apply, with index of 'Time' and
|
|
575
|
+
dataseries for 'Operating Rules'
|
|
576
|
+
varrules (List[dict]): List of logical variable rules to use. Each varrule is represented as a Dictionary with keys 'name' and 'logic'.
|
|
577
|
+
time_varrule_data (pandas.Series): Series containing data on which operating rules to apply, with index of 'Time' and
|
|
578
|
+
dataseries for 'Operating Rules'
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
**Radial Type (``SLUICE.subtype == 'RADIAL'``)**
|
|
582
|
+
|
|
583
|
+
Args:
|
|
584
|
+
use_degrees (bool): Whether to measure gate movement in degrees
|
|
585
|
+
allow_free_flow_under (bool): Whether to allow free flow under gate
|
|
586
|
+
pivot_height (float): Height of gate pivot (m) above sill
|
|
587
|
+
gate_radius (float): Distance from gate pivot to surface (m)
|
|
588
|
+
|
|
589
|
+
Returns:
|
|
590
|
+
SLUICE: Flood Modeller SLUICE Unit class object
|
|
591
|
+
"""
|
|
592
|
+
|
|
593
|
+
_unit = "SLUICE"
|
|
594
|
+
|
|
595
|
+
def _read(self, block):
|
|
596
|
+
"""Function to read a given SLUICE block and store data as class attributes"""
|
|
597
|
+
self._subtype = block[1].split(" ")[0].strip()
|
|
598
|
+
|
|
599
|
+
# Extends label line to be correct length before splitting to pick up blank labels
|
|
600
|
+
labels = split_n_char(f"{block[2]:<{3*self._label_len}}", self._label_len)
|
|
601
|
+
self.name = labels[0]
|
|
602
|
+
self.ds_label = labels[1]
|
|
603
|
+
self.remote_label = labels[2]
|
|
604
|
+
self.comment = block[0].replace("SLUICE", "").strip()
|
|
605
|
+
|
|
606
|
+
# First parameter line
|
|
607
|
+
params1 = split_10_char(f"{block[3]:<80}")
|
|
608
|
+
self.weir_flow_coefficient = _to_float(params1[0], 1.0)
|
|
609
|
+
self.under_gate_flow = _to_float(params1[1], 1.0)
|
|
610
|
+
self.weir_breadth = _to_float(params1[2])
|
|
611
|
+
self.crest_elevation = _to_float(params1[3])
|
|
612
|
+
self.gate_height_or_chord = _to_float(params1[4])
|
|
613
|
+
self.weir_length = _to_float(params1[5])
|
|
614
|
+
if self.subtype == "RADIAL":
|
|
615
|
+
self.use_degrees = params1[6] == "DEGREES"
|
|
616
|
+
self.allow_free_flow_under = params1[7] == "FREESLUICE"
|
|
617
|
+
|
|
618
|
+
# Second parameter line
|
|
619
|
+
params2 = split_10_char(f"{block[4]:<70}")
|
|
620
|
+
self.us_weir_height = _to_float(params2[0])
|
|
621
|
+
self.ds_weir_height = _to_float(params2[1])
|
|
622
|
+
self.bias_factor = _to_float(params2[2], 1.0)
|
|
623
|
+
self.over_gate_flow = _to_float(params2[3], 1.0)
|
|
624
|
+
if self.subtype == "RADIAL":
|
|
625
|
+
self.pivot_height = _to_float(params2[4], 0.7)
|
|
626
|
+
self.gate_radius = _to_float(params2[5], 0.7)
|
|
627
|
+
else:
|
|
628
|
+
self.modular_limits = {
|
|
629
|
+
"weir_flow": _to_float(params2[4]),
|
|
630
|
+
"under_gate_flow": _to_float(params2[5], 1.0),
|
|
631
|
+
"over_gate_flow": _to_float(params2[6], 1.0),
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
# Third parameter line
|
|
635
|
+
params3 = split_10_char(f"{block[5]:<60}")
|
|
636
|
+
self.ngates = int(params3[0]) # number of gates
|
|
637
|
+
if self.subtype == "RADIAL":
|
|
638
|
+
self.modular_limits = {
|
|
639
|
+
"weir_flow": _to_float(params3[1]),
|
|
640
|
+
"under_gate_flow": _to_float(params3[2], 1.0),
|
|
641
|
+
"over_gate_flow": _to_float(params3[3], 1.0),
|
|
642
|
+
}
|
|
643
|
+
self.timeunit = _to_str(params3[4], "SECONDS", check_float=True)
|
|
644
|
+
self.extendmethod = _to_str(params3[5], "EXTEND")
|
|
645
|
+
else:
|
|
646
|
+
self.timeunit = _to_str(params3[1], "SECONDS", check_float=True)
|
|
647
|
+
self.extendmethod = _to_str(params3[2], "EXTEND")
|
|
648
|
+
|
|
649
|
+
# Control lines
|
|
650
|
+
self.control_method = block[6].split()[0].upper()
|
|
651
|
+
if self.control_method == "TIME":
|
|
652
|
+
self.gates = self._get_gates(self.ngates, block, gate_row=7)
|
|
653
|
+
|
|
654
|
+
elif self.control_method == "LOGICAL":
|
|
655
|
+
logical_params = split_10_char(block[6])
|
|
656
|
+
self.max_movement_rate = logical_params[1]
|
|
657
|
+
self.max_setting = logical_params[2]
|
|
658
|
+
self.min_setting = logical_params[3]
|
|
659
|
+
self.gates = self._get_gates(self.ngates, block, gate_row=7)
|
|
660
|
+
self._read_rules(block)
|
|
661
|
+
|
|
662
|
+
else:
|
|
663
|
+
self._raw_extra_lines = block[6:]
|
|
664
|
+
print(
|
|
665
|
+
f"Note: Sluice control using method: {self.control_method} is not currently supported.",
|
|
666
|
+
)
|
|
667
|
+
|
|
668
|
+
def _write(self):
|
|
669
|
+
"""Function to write a valid SLUICE block"""
|
|
670
|
+
_validate_unit(self) # Function to check the params are valid for CONDUIT unit
|
|
671
|
+
header = "SLUICE " + self.comment
|
|
672
|
+
labels = join_n_char_ljust(self._label_len, self.name, self.ds_label, self.remote_label)
|
|
673
|
+
block = [header, self.subtype, labels]
|
|
674
|
+
|
|
675
|
+
# First parameter line
|
|
676
|
+
params1 = join_10_char(
|
|
677
|
+
self.weir_flow_coefficient,
|
|
678
|
+
self.under_gate_flow,
|
|
679
|
+
self.weir_breadth,
|
|
680
|
+
self.crest_elevation,
|
|
681
|
+
self.gate_height_or_chord,
|
|
682
|
+
self.weir_length,
|
|
683
|
+
)
|
|
684
|
+
if self.subtype == "RADIAL":
|
|
685
|
+
params1 += f'{"DEGREES":<10}' if self.use_degrees else f'{"":<10}'
|
|
686
|
+
params1 += "FREESLUICE" if self.allow_free_flow_under else f'{"":<10}'
|
|
687
|
+
|
|
688
|
+
# Second parameter line
|
|
689
|
+
params2 = join_10_char(
|
|
690
|
+
self.us_weir_height,
|
|
691
|
+
self.ds_weir_height,
|
|
692
|
+
self.bias_factor,
|
|
693
|
+
self.over_gate_flow,
|
|
694
|
+
)
|
|
695
|
+
|
|
696
|
+
if self.subtype == "RADIAL":
|
|
697
|
+
params2 += join_10_char(self.pivot_height, self.gate_radius)
|
|
698
|
+
else:
|
|
699
|
+
params2 += join_10_char(
|
|
700
|
+
self.modular_limits["weir_flow"],
|
|
701
|
+
self.modular_limits["under_gate_flow"],
|
|
702
|
+
self.modular_limits["over_gate_flow"],
|
|
703
|
+
)
|
|
704
|
+
|
|
705
|
+
# Third parameter line
|
|
706
|
+
self.ngates = len(self.gates)
|
|
707
|
+
params3 = join_10_char(self.ngates)
|
|
708
|
+
|
|
709
|
+
if self.subtype == "RADIAL":
|
|
710
|
+
params3 += join_10_char(
|
|
711
|
+
self.modular_limits["weir_flow"],
|
|
712
|
+
self.modular_limits["under_gate_flow"],
|
|
713
|
+
self.modular_limits["over_gate_flow"],
|
|
714
|
+
)
|
|
715
|
+
|
|
716
|
+
params3 += join_n_char_ljust(10, self.timeunit, self.extendmethod)
|
|
717
|
+
|
|
718
|
+
block.extend([params1, params2, params3])
|
|
719
|
+
|
|
720
|
+
# Control lines
|
|
721
|
+
if self.control_method == "TIME":
|
|
722
|
+
block.append("TIME")
|
|
723
|
+
n = 1
|
|
724
|
+
for gate in self.gates:
|
|
725
|
+
block.append(f"GATE {n}")
|
|
726
|
+
nrows = len(gate)
|
|
727
|
+
block.append(f"{nrows:>10}")
|
|
728
|
+
gate_data = [f"{join_10_char(t, o)}" for t, o in gate.items()]
|
|
729
|
+
block.extend(gate_data)
|
|
730
|
+
n += 1
|
|
731
|
+
|
|
732
|
+
elif self.control_method == "LOGICAL":
|
|
733
|
+
# ADD GATES
|
|
734
|
+
block.append(
|
|
735
|
+
join_10_char(
|
|
736
|
+
f'{"LOGICAL":<10}',
|
|
737
|
+
self.max_movement_rate,
|
|
738
|
+
self.max_setting,
|
|
739
|
+
self.min_setting,
|
|
740
|
+
),
|
|
741
|
+
)
|
|
742
|
+
n = 1
|
|
743
|
+
for gate in self.gates:
|
|
744
|
+
block.append(f"GATE {n}")
|
|
745
|
+
nrows = len(gate)
|
|
746
|
+
block.append(f"{nrows:>10}")
|
|
747
|
+
gate_data = [f"{join_10_char(t, m, o)}" for t, m, o in gate.itertuples()]
|
|
748
|
+
block.extend(gate_data)
|
|
749
|
+
n += 1
|
|
750
|
+
block = self._write_rules(block)
|
|
751
|
+
|
|
752
|
+
else:
|
|
753
|
+
block.extend(self._raw_extra_lines)
|
|
754
|
+
|
|
755
|
+
return block
|
|
756
|
+
|
|
757
|
+
def _get_gates(self, ngates, block, gate_row):
|
|
758
|
+
gates = []
|
|
759
|
+
|
|
760
|
+
if self.control_method == "TIME":
|
|
761
|
+
for _ in range(ngates):
|
|
762
|
+
nrows = int(split_10_char(block[gate_row + 1])[0])
|
|
763
|
+
data_list = []
|
|
764
|
+
for row in block[gate_row + 2 : gate_row + 2 + nrows]:
|
|
765
|
+
row_split = split_10_char(f"{row:<20}")
|
|
766
|
+
x = _to_float(row_split[0]) # time
|
|
767
|
+
y = _to_float(row_split[1]) # opening
|
|
768
|
+
data_list.append([x, y])
|
|
769
|
+
|
|
770
|
+
gate_data = pd.DataFrame(data_list, columns=["Time", "Opening"])
|
|
771
|
+
gate_data = gate_data.set_index("Time")
|
|
772
|
+
gate_data = gate_data["Opening"]
|
|
773
|
+
|
|
774
|
+
gates.append(gate_data)
|
|
775
|
+
|
|
776
|
+
gate_row += 2 + nrows
|
|
777
|
+
|
|
778
|
+
self._last_gate_row = gate_row
|
|
779
|
+
|
|
780
|
+
return gates
|
|
781
|
+
|
|
782
|
+
if self.control_method == "LOGICAL":
|
|
783
|
+
for _ in range(ngates):
|
|
784
|
+
nrows = int(split_10_char(block[gate_row + 1])[0])
|
|
785
|
+
data_list = []
|
|
786
|
+
for row in block[gate_row + 2 : gate_row + 2 + nrows]:
|
|
787
|
+
row_split = split_10_char(f"{row:<30}")
|
|
788
|
+
x = _to_float(row_split[0]) # time
|
|
789
|
+
y = row_split[1] # mode
|
|
790
|
+
z = _to_float(row_split[2]) # opening
|
|
791
|
+
data_list.append([x, y, z])
|
|
792
|
+
|
|
793
|
+
gate_data = pd.DataFrame(data_list, columns=["Time", "Mode", "Opening"])
|
|
794
|
+
gate_data = gate_data.set_index("Time")
|
|
795
|
+
|
|
796
|
+
gates.append(gate_data)
|
|
797
|
+
|
|
798
|
+
gate_row += 2 + nrows
|
|
799
|
+
|
|
800
|
+
self._last_gate_row = gate_row
|
|
801
|
+
|
|
802
|
+
return gates
|
|
803
|
+
return None
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
class ORIFICE(Unit):
|
|
807
|
+
"""Class to hold and process ORIFICE unit type
|
|
808
|
+
|
|
809
|
+
Args:
|
|
810
|
+
name (str, optional): Unit name.
|
|
811
|
+
comment (str, optional): Comment included in unit.
|
|
812
|
+
flapped (bool, optional): ``True`` if orifice is flapped, ``False`` if orifice is open
|
|
813
|
+
ds_label (str, optional): Downstream label
|
|
814
|
+
invert (float, optional): Throat invert level
|
|
815
|
+
soffit (float, optional): Throat soffit level
|
|
816
|
+
bore_area (float, optional): Cross sectional area of throat opening
|
|
817
|
+
upstream_sill (float, optional): Upstream sill level
|
|
818
|
+
downstream_sill (float, optional): Downstream sill level
|
|
819
|
+
shape (str, optional): Shape of orifice aperture ('RECTANGLE' or 'CIRCULAR')
|
|
820
|
+
weir_flow (float, optional): Calibration factor for weir flow
|
|
821
|
+
surcharged_flow (float, optional): Calibration factor for surcharged flow
|
|
822
|
+
modular_limit (float, optional): Ratio of upstream and downstream heads when switching between free and drowned mode
|
|
823
|
+
|
|
824
|
+
|
|
825
|
+
Returns:
|
|
826
|
+
ORIFICE: Flood Modeller ORIFICE Unit class object
|
|
827
|
+
"""
|
|
828
|
+
|
|
829
|
+
_unit = "ORIFICE"
|
|
830
|
+
|
|
831
|
+
def _read(self, block):
|
|
832
|
+
"""Function to read a given ORIFICE block and store data as class attributes"""
|
|
833
|
+
self._subtype = block[1].split(" ")[0].strip()
|
|
834
|
+
self.flapped = self.subtype == "FLAPPED"
|
|
835
|
+
|
|
836
|
+
# Extends label line to be correct length before splitting to pick up blank labels
|
|
837
|
+
labels = split_n_char(f"{block[2]:<{2*self._label_len}}", self._label_len)
|
|
838
|
+
self.name = labels[0]
|
|
839
|
+
self.ds_label = labels[1]
|
|
840
|
+
self.comment = block[0].replace("ORIFICE", "").strip()
|
|
841
|
+
|
|
842
|
+
# First parameter line
|
|
843
|
+
params1 = split_10_char(f"{block[3]:<60}")
|
|
844
|
+
self.invert = _to_float(params1[0])
|
|
845
|
+
self.soffit = _to_float(params1[1])
|
|
846
|
+
self.bore_area = _to_float(params1[2])
|
|
847
|
+
self.upstream_sill = _to_float(params1[3])
|
|
848
|
+
self.downstream_sill = _to_float(params1[4])
|
|
849
|
+
self.shape = _to_str(params1[5], "RECTANGLE")
|
|
850
|
+
|
|
851
|
+
# Second parameter line
|
|
852
|
+
params2 = split_10_char(block[4])
|
|
853
|
+
self.weir_flow = _to_float(params2[0], 1.0)
|
|
854
|
+
self.surcharged_flow = _to_float(params2[1], 1.0)
|
|
855
|
+
self.modular_limit = _to_float(params2[2], 0.7)
|
|
856
|
+
|
|
857
|
+
def _write(self):
|
|
858
|
+
"""Function to write a valid ORIFICE block"""
|
|
859
|
+
_validate_unit(self) # Function to check the params are valid for CONDUIT unit
|
|
860
|
+
header = "ORIFICE " + self.comment
|
|
861
|
+
labels = join_n_char_ljust(self._label_len, self.name, self.ds_label)
|
|
862
|
+
|
|
863
|
+
self._subtype = "FLAPPED" if self.flapped else "OPEN"
|
|
864
|
+
block = [header, self.subtype, labels]
|
|
865
|
+
|
|
866
|
+
# First parameter line
|
|
867
|
+
params1 = join_10_char(
|
|
868
|
+
self.invert,
|
|
869
|
+
self.soffit,
|
|
870
|
+
self.bore_area,
|
|
871
|
+
self.upstream_sill,
|
|
872
|
+
self.downstream_sill,
|
|
873
|
+
self.shape,
|
|
874
|
+
)
|
|
875
|
+
|
|
876
|
+
# Second parameter line
|
|
877
|
+
params2 = join_10_char(self.weir_flow, self.surcharged_flow, self.modular_limit)
|
|
878
|
+
|
|
879
|
+
block.extend([params1, params2])
|
|
880
|
+
|
|
881
|
+
return block
|
|
882
|
+
|
|
883
|
+
def _create_from_blank( # noqa: PLR0913
|
|
884
|
+
self,
|
|
885
|
+
name="new_orifice",
|
|
886
|
+
flapped=False,
|
|
887
|
+
ds_label="",
|
|
888
|
+
comment="",
|
|
889
|
+
invert=0.0,
|
|
890
|
+
soffit=0.0,
|
|
891
|
+
bore_area=1.0,
|
|
892
|
+
upstream_sill=0.0,
|
|
893
|
+
downstream_sill=0.0,
|
|
894
|
+
shape="RECTANGLE",
|
|
895
|
+
weir_flow=1.0,
|
|
896
|
+
surcharged_flow=1.0,
|
|
897
|
+
modular_limit=0.7,
|
|
898
|
+
):
|
|
899
|
+
for param, val in {
|
|
900
|
+
"name": name,
|
|
901
|
+
"flapped": flapped,
|
|
902
|
+
"ds_label": ds_label,
|
|
903
|
+
"comment": comment,
|
|
904
|
+
"invert": invert,
|
|
905
|
+
"soffit": soffit,
|
|
906
|
+
"bore_area": bore_area,
|
|
907
|
+
"upstream_sill": upstream_sill,
|
|
908
|
+
"downstream_sill": downstream_sill,
|
|
909
|
+
"shape": shape,
|
|
910
|
+
"weir_flow": weir_flow,
|
|
911
|
+
"surcharged_flow": surcharged_flow,
|
|
912
|
+
"modular_limit": modular_limit,
|
|
913
|
+
}.items():
|
|
914
|
+
setattr(self, param, val)
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
class SPILL(Unit):
|
|
918
|
+
"""Class to hold and process SPILL unit type
|
|
919
|
+
|
|
920
|
+
Args:
|
|
921
|
+
name (str, optional): Unit name.
|
|
922
|
+
comment (str, optional): Comment included in unit.
|
|
923
|
+
ds_label (str, optional): Downstream label
|
|
924
|
+
weir_coefficient (float, optional): Weir coefficient
|
|
925
|
+
modular_limit (float, optional): Ratio of upstream and downstream heads when switching between free and drowned mode
|
|
926
|
+
data (pandas.DataFrame): Dataframe object containing all the spill section data.
|
|
927
|
+
Columns are ``'X', 'Y', 'Easting', 'Northing'``
|
|
928
|
+
|
|
929
|
+
Returns:
|
|
930
|
+
SPILL: Flood Modeller SPILL Unit class object
|
|
931
|
+
"""
|
|
932
|
+
|
|
933
|
+
_unit = "SPILL"
|
|
934
|
+
|
|
935
|
+
def _read(self, block):
|
|
936
|
+
"""Function to read a given SPILL block and store data as class attributes"""
|
|
937
|
+
# Extends label line to be correct length before splitting to pick up blank labels
|
|
938
|
+
labels = split_n_char(f"{block[1]:<{2*self._label_len}}", self._label_len)
|
|
939
|
+
self.name = labels[0]
|
|
940
|
+
self.ds_label = labels[1]
|
|
941
|
+
self.comment = block[0].replace("SPILL", "").strip()
|
|
942
|
+
|
|
943
|
+
# First parameter line
|
|
944
|
+
params = split_10_char(block[2])
|
|
945
|
+
self.weir_coefficient = _to_float(params[0], 1.2)
|
|
946
|
+
self.modular_limit = _to_float(params[1], 0.9)
|
|
947
|
+
|
|
948
|
+
# Spill section data
|
|
949
|
+
data_list = []
|
|
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
|
|
961
|
+
|
|
962
|
+
def _write(self):
|
|
963
|
+
"""Function to write a valid SPILL block"""
|
|
964
|
+
_validate_unit(self) # Function to check the params are valid for CONDUIT unit
|
|
965
|
+
header = "SPILL " + self.comment
|
|
966
|
+
labels = join_n_char_ljust(self._label_len, self.name, self.ds_label)
|
|
967
|
+
block = [header, labels]
|
|
968
|
+
|
|
969
|
+
# First parameter line
|
|
970
|
+
params = join_10_char(self.weir_coefficient, self.modular_limit)
|
|
971
|
+
block.append(params)
|
|
972
|
+
|
|
973
|
+
# Section data
|
|
974
|
+
nrows = len(self.data)
|
|
975
|
+
block.append(join_10_char(nrows))
|
|
976
|
+
section_data = [join_10_char(x, y, e, n) for _, x, y, e, n in self.data.itertuples()]
|
|
977
|
+
block.extend(section_data)
|
|
978
|
+
|
|
979
|
+
return block
|
|
980
|
+
|
|
981
|
+
def _create_from_blank( # noqa: PLR0913
|
|
982
|
+
self,
|
|
983
|
+
name="new_spill",
|
|
984
|
+
ds_label="",
|
|
985
|
+
comment="",
|
|
986
|
+
weir_coefficient=1.2,
|
|
987
|
+
modular_limit=0.9,
|
|
988
|
+
data=None,
|
|
989
|
+
):
|
|
990
|
+
for param, val in {
|
|
991
|
+
"name": name,
|
|
992
|
+
"ds_label": ds_label,
|
|
993
|
+
"comment": comment,
|
|
994
|
+
"weir_coefficient": weir_coefficient,
|
|
995
|
+
"modular_limit": modular_limit,
|
|
996
|
+
}.items():
|
|
997
|
+
setattr(self, param, val)
|
|
998
|
+
|
|
999
|
+
self.data = (
|
|
1000
|
+
data
|
|
1001
|
+
if isinstance(data, pd.DataFrame)
|
|
1002
|
+
else pd.DataFrame([[0.0, 0.0, 0.0, 0.0]], columns=["X", "Y", "Easting", "Northing"])
|
|
1003
|
+
)
|
|
1004
|
+
|
|
1005
|
+
|
|
1006
|
+
class RNWEIR(Unit):
|
|
1007
|
+
"""Class to hold and process RNWEIR unit type
|
|
1008
|
+
|
|
1009
|
+
Args:
|
|
1010
|
+
name (str, optional): Upstream label name.
|
|
1011
|
+
comment (str, optional): Comment included in unit.
|
|
1012
|
+
ds_label (str, optional): Downstream label.
|
|
1013
|
+
velocity_coefficient (float, optional): Coefficient of approach velocity.
|
|
1014
|
+
weir_length (float, optional): Length of weir crest in the direction of flow (m).
|
|
1015
|
+
weir_breadth (float, optional): Breadth of weir at control section (normal to the flow direction)(m).
|
|
1016
|
+
weir_elevation (float, optional): Elevation of weir crest (m AD).
|
|
1017
|
+
modular_limit (float, optional): Ratio of upstream and downstream heads when switching between free and drowned mode.
|
|
1018
|
+
upstream_crest_height (float, optional): Height of crest above bed of upstream channnel (m).
|
|
1019
|
+
downstream_crest_height (float, optional): Height of crest above downstream channel (m).
|
|
1020
|
+
|
|
1021
|
+
Returns:
|
|
1022
|
+
RNWEIR: Flood Modeller RNWEIR Unit class object"""
|
|
1023
|
+
|
|
1024
|
+
_unit = "RNWEIR"
|
|
1025
|
+
ACCEPTABLE_MODULAR_LIMIT = 0.0
|
|
1026
|
+
|
|
1027
|
+
def _read(self, block):
|
|
1028
|
+
"""Function to read a given RNWEIR block and store data as class attributes"""
|
|
1029
|
+
# Extends label line to be correct length before splitting to pick up blank labels
|
|
1030
|
+
labels = split_n_char(f"{block[1]:<{2*self._label_len}}", self._label_len)
|
|
1031
|
+
self.name = labels[0]
|
|
1032
|
+
self.ds_label = labels[1]
|
|
1033
|
+
self.comment = block[0].replace("RNWEIR", "").strip()
|
|
1034
|
+
|
|
1035
|
+
# First parameter line
|
|
1036
|
+
params1 = split_10_char(f"{block[2]:<50}")
|
|
1037
|
+
self.velocity_coefficient = _to_float(params1[0])
|
|
1038
|
+
self.weir_length = _to_float(params1[1])
|
|
1039
|
+
self.weir_breadth = _to_float(params1[2])
|
|
1040
|
+
self.weir_elevation = _to_float(params1[3])
|
|
1041
|
+
self.modular_limit = _to_float(params1[4])
|
|
1042
|
+
|
|
1043
|
+
# Second parameter line
|
|
1044
|
+
params2 = split_10_char(f"{block[3]:<20}")
|
|
1045
|
+
self.upstream_crest_height = _to_float(params2[0])
|
|
1046
|
+
self.downstream_crest_height = _to_float(params2[1])
|
|
1047
|
+
|
|
1048
|
+
def _write(self):
|
|
1049
|
+
"""Function to write a valid RNWEIR block"""
|
|
1050
|
+
_validate_unit(self)
|
|
1051
|
+
header = "RNWEIR " + self.comment
|
|
1052
|
+
labels = join_n_char_ljust(self._label_len, self.name, self.ds_label)
|
|
1053
|
+
block = [header, labels]
|
|
1054
|
+
|
|
1055
|
+
# First parameter line
|
|
1056
|
+
if self.modular_limit == self.ACCEPTABLE_MODULAR_LIMIT:
|
|
1057
|
+
params1 = join_10_char(
|
|
1058
|
+
self.velocity_coefficient,
|
|
1059
|
+
self.weir_length,
|
|
1060
|
+
self.weir_breadth,
|
|
1061
|
+
self.weir_elevation,
|
|
1062
|
+
)
|
|
1063
|
+
else:
|
|
1064
|
+
params1 = join_10_char(
|
|
1065
|
+
self.velocity_coefficient,
|
|
1066
|
+
self.weir_length,
|
|
1067
|
+
self.weir_breadth,
|
|
1068
|
+
self.weir_elevation,
|
|
1069
|
+
self.modular_limit,
|
|
1070
|
+
)
|
|
1071
|
+
|
|
1072
|
+
block.append(params1)
|
|
1073
|
+
|
|
1074
|
+
# Second parameter line
|
|
1075
|
+
params2 = join_10_char(self.upstream_crest_height, self.downstream_crest_height)
|
|
1076
|
+
block.append(params2)
|
|
1077
|
+
|
|
1078
|
+
return block
|
|
1079
|
+
|
|
1080
|
+
def _create_from_blank( # noqa: PLR0913
|
|
1081
|
+
self,
|
|
1082
|
+
name="new_rnweir",
|
|
1083
|
+
comment="",
|
|
1084
|
+
ds_label="",
|
|
1085
|
+
velocity_coefficient=1.0,
|
|
1086
|
+
modular_limit=0.7,
|
|
1087
|
+
upstream_crest_height=0.0,
|
|
1088
|
+
downstream_crest_height=0.0,
|
|
1089
|
+
weir_length=0.0,
|
|
1090
|
+
weir_breadth=0.0,
|
|
1091
|
+
weir_elevation=0.0,
|
|
1092
|
+
):
|
|
1093
|
+
for param, val in {
|
|
1094
|
+
"name": name,
|
|
1095
|
+
"comment": comment,
|
|
1096
|
+
"ds_label": ds_label,
|
|
1097
|
+
"velocity_coefficient": velocity_coefficient,
|
|
1098
|
+
"modular_limit": modular_limit,
|
|
1099
|
+
"upstream_crest_height": upstream_crest_height,
|
|
1100
|
+
"downstream_crest_height": downstream_crest_height,
|
|
1101
|
+
"weir_length": weir_length,
|
|
1102
|
+
"wier_breadth": weir_breadth,
|
|
1103
|
+
"weir_elevation": weir_elevation,
|
|
1104
|
+
}.items():
|
|
1105
|
+
setattr(self, param, val)
|
|
1106
|
+
|
|
1107
|
+
|
|
1108
|
+
class WEIR(Unit):
|
|
1109
|
+
"""Class to hold and process WEIR unit type
|
|
1110
|
+
|
|
1111
|
+
Args:
|
|
1112
|
+
name (str, optional): Upstream label name.
|
|
1113
|
+
comment (str, optional): Comment included in unit.
|
|
1114
|
+
ds_label (str, optional): Downstream label.
|
|
1115
|
+
exponent (float, optional): Coefficient of discharge for the weir,
|
|
1116
|
+
discharge_coefficeient (float, optional): Exponent used in the weir flow equation,
|
|
1117
|
+
velocity_coefficient (float, optional): Coefficient of approach velocity.
|
|
1118
|
+
weir_length (float, optional): Length of weir crest in the direction of flow (m).
|
|
1119
|
+
weir_breadth (float, optional): Breadth of weir at control section (normal to the flow direction)(m).
|
|
1120
|
+
weir_elevation (float, optional): Elevation of weir crest (m AD).
|
|
1121
|
+
modular_limit (float, optional): Ratio of upstream and downstream heads when switching between free and drowned mode.
|
|
1122
|
+
|
|
1123
|
+
Returns:
|
|
1124
|
+
WEIR: Flood Modeller WEIR Unit class object"""
|
|
1125
|
+
|
|
1126
|
+
_unit = "WEIR"
|
|
1127
|
+
|
|
1128
|
+
def _read(self, block):
|
|
1129
|
+
"""Function to read a given WEIR block and store data as class attributes"""
|
|
1130
|
+
# Extends label line to be correct length before splitting to pick up blank labels
|
|
1131
|
+
labels = split_n_char(f"{block[1]:<{2*self._label_len}}", self._label_len)
|
|
1132
|
+
self.name = labels[0]
|
|
1133
|
+
self.ds_label = labels[1]
|
|
1134
|
+
self.comment = block[0].replace("WEIR", "").strip()
|
|
1135
|
+
|
|
1136
|
+
# Exponent
|
|
1137
|
+
self.exponent = _to_float(block[2].strip())
|
|
1138
|
+
|
|
1139
|
+
# Parameters line
|
|
1140
|
+
params = split_10_char(f"{block[3]:<50}")
|
|
1141
|
+
self.discharge_coefficient = _to_float(params[0])
|
|
1142
|
+
self.velocity_coefficient = _to_float(params[1])
|
|
1143
|
+
self.weir_breadth = _to_float(params[2])
|
|
1144
|
+
self.weir_elevation = _to_float(params[3])
|
|
1145
|
+
self.modular_limit = _to_float(params[4])
|
|
1146
|
+
|
|
1147
|
+
def _write(self):
|
|
1148
|
+
"""Function to write a valid WEIR block"""
|
|
1149
|
+
_validate_unit(self)
|
|
1150
|
+
header = "WEIR " + self.comment
|
|
1151
|
+
labels = join_n_char_ljust(self._label_len, self.name, self.ds_label)
|
|
1152
|
+
block = [header, labels]
|
|
1153
|
+
|
|
1154
|
+
# Exponent line
|
|
1155
|
+
exp_line = join_10_char(self.exponent)
|
|
1156
|
+
block.append(exp_line)
|
|
1157
|
+
|
|
1158
|
+
# Parameter line
|
|
1159
|
+
params = join_10_char(
|
|
1160
|
+
self.discharge_coefficient,
|
|
1161
|
+
self.velocity_coefficient,
|
|
1162
|
+
self.weir_breadth,
|
|
1163
|
+
self.weir_elevation,
|
|
1164
|
+
self.modular_limit,
|
|
1165
|
+
)
|
|
1166
|
+
block.append(params)
|
|
1167
|
+
|
|
1168
|
+
return block
|
|
1169
|
+
|
|
1170
|
+
def _create_from_blank( # noqa: PLR0913
|
|
1171
|
+
self,
|
|
1172
|
+
name="new_weir",
|
|
1173
|
+
comment="",
|
|
1174
|
+
ds_label="",
|
|
1175
|
+
exponent=1.5,
|
|
1176
|
+
discharge_coefficeient=1.0,
|
|
1177
|
+
velocity_coefficient=1.0,
|
|
1178
|
+
modular_limit=0.7,
|
|
1179
|
+
weir_length=0.0,
|
|
1180
|
+
weir_breadth=0.0,
|
|
1181
|
+
weir_elevation=0.0,
|
|
1182
|
+
):
|
|
1183
|
+
for param, val in {
|
|
1184
|
+
"name": name,
|
|
1185
|
+
"comment": comment,
|
|
1186
|
+
"ds_label": ds_label,
|
|
1187
|
+
"exponent": exponent,
|
|
1188
|
+
"discharge_coefficeient": discharge_coefficeient,
|
|
1189
|
+
"velocity_coefficient": velocity_coefficient,
|
|
1190
|
+
"modular_limit": modular_limit,
|
|
1191
|
+
"weir_length": weir_length,
|
|
1192
|
+
"wier_breadth": weir_breadth,
|
|
1193
|
+
"weir_elevation": weir_elevation,
|
|
1194
|
+
}.items():
|
|
1195
|
+
setattr(self, param, val)
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
class CRUMP(Unit):
|
|
1199
|
+
"""Class to hold and process CRUMP unit type
|
|
1200
|
+
|
|
1201
|
+
Args:
|
|
1202
|
+
name (str, optional): Upstream label name.
|
|
1203
|
+
comment (str,optional): Comment included in unit.
|
|
1204
|
+
calibration_coefficient (float, optional): Calibration coefficient (should be set to unity for most cases).
|
|
1205
|
+
weir_breadth (float, optional): Breadth of weir at crest (m).
|
|
1206
|
+
weir_elevation (float, optional): Eleveation of weir crest (m above datum).
|
|
1207
|
+
modular_limit (float, optional): Ratio of upstream and downstream heads when switching between free and drowned mode.
|
|
1208
|
+
upstream_crest_height (float, optional): Height of crest above bed of upstream channel (m).
|
|
1209
|
+
downstream_crest_height (float, optional): Height oof crest above bed of downstream channel (m).
|
|
1210
|
+
ds_label (str, optional): Downstream node label.
|
|
1211
|
+
us_remote_label (str, optional): Upstream remote node label (must be a river or conduit section) - use if name is not a river or conduit section.
|
|
1212
|
+
ds_remote_label (str, optional): Downstream remote node label (must be a river or conduit section) - use if ds_label is not a river or conduit section.
|
|
1213
|
+
|
|
1214
|
+
Returns:
|
|
1215
|
+
CRUMP: Flood Modeller CRUMP Unit class object"""
|
|
1216
|
+
|
|
1217
|
+
_unit = "CRUMP"
|
|
1218
|
+
ACCEPTABLE_MODULAR_LIMIT = 0.0
|
|
1219
|
+
|
|
1220
|
+
def _read(self, block):
|
|
1221
|
+
"""Function to read a given CRUMP block and store data as class attributes"""
|
|
1222
|
+
# Extends label line to be correct length before splitting to pick up blank labels
|
|
1223
|
+
labels = split_n_char(f"{block[1]:<{4*self._label_len}}", self._label_len)
|
|
1224
|
+
self.name = labels[0]
|
|
1225
|
+
self.ds_label = labels[1]
|
|
1226
|
+
self.us_remote_label = labels[2]
|
|
1227
|
+
self.ds_remote_label = labels[3]
|
|
1228
|
+
self.comment = block[0].replace("CRUMP", "").strip()
|
|
1229
|
+
|
|
1230
|
+
# First parameter line
|
|
1231
|
+
params1 = split_10_char(f"{block[2]:<40}")
|
|
1232
|
+
self.calibration_coefficient = _to_float(params1[0])
|
|
1233
|
+
self.weir_breadth = _to_float(params1[1])
|
|
1234
|
+
self.weir_elevation = _to_float(params1[2])
|
|
1235
|
+
self.modular_limit = _to_float(params1[3])
|
|
1236
|
+
|
|
1237
|
+
# Second parameter line
|
|
1238
|
+
params2 = split_10_char(f"{block[3]:<20}")
|
|
1239
|
+
self.upstream_crest_height = _to_float(params2[0])
|
|
1240
|
+
self.downstream_crest_height = _to_float(params2[1])
|
|
1241
|
+
|
|
1242
|
+
def _write(self):
|
|
1243
|
+
"""Function to write a valid CRUMP block"""
|
|
1244
|
+
_validate_unit(self)
|
|
1245
|
+
header = "CRUMP " + self.comment
|
|
1246
|
+
labels = join_n_char_ljust(
|
|
1247
|
+
self._label_len,
|
|
1248
|
+
self.name,
|
|
1249
|
+
self.ds_label,
|
|
1250
|
+
self.us_remote_label,
|
|
1251
|
+
self.ds_remote_label,
|
|
1252
|
+
)
|
|
1253
|
+
block = [header, labels]
|
|
1254
|
+
|
|
1255
|
+
# First parameter line
|
|
1256
|
+
params1 = join_10_char(
|
|
1257
|
+
self.calibration_coefficient,
|
|
1258
|
+
self.weir_breadth,
|
|
1259
|
+
self.weir_elevation,
|
|
1260
|
+
self.modular_limit if self.modular_limit != self.ACCEPTABLE_MODULAR_LIMIT else "",
|
|
1261
|
+
)
|
|
1262
|
+
|
|
1263
|
+
block.append(params1)
|
|
1264
|
+
|
|
1265
|
+
# Second parameter line
|
|
1266
|
+
params2 = join_10_char(self.upstream_crest_height, self.downstream_crest_height)
|
|
1267
|
+
block.append(params2)
|
|
1268
|
+
|
|
1269
|
+
return block
|
|
1270
|
+
|
|
1271
|
+
def _create_from_blank( # noqa: PLR0913
|
|
1272
|
+
self,
|
|
1273
|
+
name="new_crump",
|
|
1274
|
+
comment="",
|
|
1275
|
+
calibration_coefficient=1.0,
|
|
1276
|
+
weir_breadth=0.0,
|
|
1277
|
+
weir_elevation=0.0,
|
|
1278
|
+
modular_limit=0.7,
|
|
1279
|
+
upstream_crest_height=0.0,
|
|
1280
|
+
downstream_crest_height=0.0,
|
|
1281
|
+
ds_label="",
|
|
1282
|
+
us_remote_label="",
|
|
1283
|
+
ds_remote_label="",
|
|
1284
|
+
):
|
|
1285
|
+
for param, val in {
|
|
1286
|
+
"name": name,
|
|
1287
|
+
"comment": comment,
|
|
1288
|
+
"calibration_coefficient": calibration_coefficient,
|
|
1289
|
+
"weir_breadth": weir_breadth,
|
|
1290
|
+
"weir_elevation": weir_elevation,
|
|
1291
|
+
"modular_limit": modular_limit,
|
|
1292
|
+
"upstream_crest_height": upstream_crest_height,
|
|
1293
|
+
"downstream_crest_height": downstream_crest_height,
|
|
1294
|
+
"ds_label": ds_label,
|
|
1295
|
+
"us_remote_label": us_remote_label,
|
|
1296
|
+
"ds_remote_label": ds_remote_label,
|
|
1297
|
+
}.items():
|
|
1298
|
+
setattr(self, param, val)
|
|
1299
|
+
|
|
1300
|
+
|
|
1301
|
+
class FLAT_V_WEIR(Unit): # noqa: N801
|
|
1302
|
+
"""Class to hold and process FLAT-V WEIR unit type
|
|
1303
|
+
|
|
1304
|
+
Args:
|
|
1305
|
+
|
|
1306
|
+
name (str, optional): Upstream label name.
|
|
1307
|
+
comment (str,optional): Comment included in unit.
|
|
1308
|
+
ds_label (str, optional): Downstream node label.
|
|
1309
|
+
us_remote_label (str, optional): Upstream remote node label (must be a river or conduit section) - use if name is not a river or conduit section.
|
|
1310
|
+
ds_remote_label (str, optional): Downstream remote node label (must be a river or conduit section) - use if ds_label is not a river or conduit section.
|
|
1311
|
+
weir_elevation (float, optional): Eleveation of weir crest (m above datum).
|
|
1312
|
+
weir_breadth (float, optional): Breadth of weir at crest (m).
|
|
1313
|
+
v_slope (float, optional): 'V' slope (horizontal distance/vertical distance).
|
|
1314
|
+
side_slope (float, optional): Channel side slope (horizontal distance/vertical distance).
|
|
1315
|
+
upstream_crest_height (float, optional): Weir crest height above upstream bed (m).
|
|
1316
|
+
downstream_crest_height (float, optional): Weir crest height above downstream bed (m).
|
|
1317
|
+
modular_limit (float, optional): Ratio of upstream and downstream heads when switching between free and drowned mode.
|
|
1318
|
+
calibration_coefficient (float, optional): Calibration coefficient (should be set to unity for most cases).
|
|
1319
|
+
ds_face_slope (int, optional): Flag to switch between 1:5 or 1:2 for d/s face. Can be set to 2 or 5 ONLY.
|
|
1320
|
+
coriolis_coefficient (float, optional): Coriolis energy coefficient.
|
|
1321
|
+
bank_top_elevation (float, optional): Elevation of channel bank top/ limit of extent of sloping channel walls (m AD).
|
|
1322
|
+
|
|
1323
|
+
Returns:
|
|
1324
|
+
FLAT_V_WEIR: Flood Modeller FLAT-V WEIR Unit class object"""
|
|
1325
|
+
|
|
1326
|
+
_unit = "FLAT-V WEIR"
|
|
1327
|
+
ACCEPTABLE_MODULAR_LIMIT = 0.0
|
|
1328
|
+
|
|
1329
|
+
def _read(self, block):
|
|
1330
|
+
"""Function to read a given FLAT-V WEIR block and store data as class attributes"""
|
|
1331
|
+
# Extends label line to be correct length before splitting to pick up blank labels
|
|
1332
|
+
labels = split_n_char(f"{block[1]:<{4*self._label_len}}", self._label_len)
|
|
1333
|
+
self.name = labels[0]
|
|
1334
|
+
self.ds_label = labels[1]
|
|
1335
|
+
self.us_remote_label = labels[2]
|
|
1336
|
+
self.ds_remote_label = labels[3]
|
|
1337
|
+
self.comment = block[0].replace("FLAT-V WEIR", "").strip()
|
|
1338
|
+
|
|
1339
|
+
# First parameter line
|
|
1340
|
+
params1 = split_10_char(f"{block[2]:<90}")
|
|
1341
|
+
self.calibration_coefficient = _to_float(params1[0])
|
|
1342
|
+
self.weir_breadth = _to_float(params1[1])
|
|
1343
|
+
self.weir_elevation = _to_float(params1[2])
|
|
1344
|
+
self.modular_limit = _to_float(params1[3])
|
|
1345
|
+
self.v_slope = _to_float(params1[4])
|
|
1346
|
+
self.side_slope = _to_float(params1[5])
|
|
1347
|
+
self.ds_face_slope = _to_float(params1[6])
|
|
1348
|
+
self.coriolis_coefficient = _to_float(params1[7])
|
|
1349
|
+
self.bank_top_elevation = _to_float(params1[8])
|
|
1350
|
+
|
|
1351
|
+
# Second parameter line
|
|
1352
|
+
params2 = split_10_char(f"{block[3]:<20}")
|
|
1353
|
+
self.upstream_crest_height = _to_float(params2[0])
|
|
1354
|
+
self.downstream_crest_height = _to_float(params2[1])
|
|
1355
|
+
|
|
1356
|
+
def _write(self):
|
|
1357
|
+
"""Function to write a valid FLAT-V WEIR block"""
|
|
1358
|
+
|
|
1359
|
+
_validate_unit(self)
|
|
1360
|
+
header = "FLAT-V WEIR " + self.comment
|
|
1361
|
+
labels = join_n_char_ljust(
|
|
1362
|
+
self._label_len,
|
|
1363
|
+
self.name,
|
|
1364
|
+
self.ds_label,
|
|
1365
|
+
self.us_remote_label,
|
|
1366
|
+
self.ds_remote_label,
|
|
1367
|
+
)
|
|
1368
|
+
block = [header, labels]
|
|
1369
|
+
|
|
1370
|
+
params1 = join_10_char(
|
|
1371
|
+
self.calibration_coefficient,
|
|
1372
|
+
self.weir_breadth,
|
|
1373
|
+
self.weir_elevation,
|
|
1374
|
+
self.modular_limit if self.modular_limit != self.ACCEPTABLE_MODULAR_LIMIT else "",
|
|
1375
|
+
self.v_slope,
|
|
1376
|
+
self.side_slope,
|
|
1377
|
+
self.ds_face_slope,
|
|
1378
|
+
self.coriolis_coefficient,
|
|
1379
|
+
self.bank_top_elevation,
|
|
1380
|
+
)
|
|
1381
|
+
|
|
1382
|
+
block.append(params1)
|
|
1383
|
+
|
|
1384
|
+
# Second parameter line
|
|
1385
|
+
params2 = join_10_char(self.upstream_crest_height, self.downstream_crest_height)
|
|
1386
|
+
block.append(params2)
|
|
1387
|
+
|
|
1388
|
+
return block
|
|
1389
|
+
|
|
1390
|
+
def _create_from_blank( # noqa: PLR0913
|
|
1391
|
+
self,
|
|
1392
|
+
name="new_flat_v",
|
|
1393
|
+
comment="",
|
|
1394
|
+
ds_label="",
|
|
1395
|
+
us_remote_label="",
|
|
1396
|
+
ds_remote_label="",
|
|
1397
|
+
weir_elevation=0.0,
|
|
1398
|
+
weir_breadth=0.0,
|
|
1399
|
+
v_slope=0.0,
|
|
1400
|
+
side_slope=0.0,
|
|
1401
|
+
upstream_crest_height=0.0,
|
|
1402
|
+
downstream_crest_height=0.0,
|
|
1403
|
+
modular_limit=0.0,
|
|
1404
|
+
calibration_coefficient=1.0,
|
|
1405
|
+
ds_face_slope=5,
|
|
1406
|
+
coriolis_coefficient=1.2,
|
|
1407
|
+
bank_top_elevation=0.0,
|
|
1408
|
+
):
|
|
1409
|
+
for param, val in {
|
|
1410
|
+
"name": name,
|
|
1411
|
+
"comment": comment,
|
|
1412
|
+
"ds_label": ds_label,
|
|
1413
|
+
"us_remote_label": us_remote_label,
|
|
1414
|
+
"ds_remote_label": ds_remote_label,
|
|
1415
|
+
"weir_elevation": weir_elevation,
|
|
1416
|
+
"weir_breadth": weir_breadth,
|
|
1417
|
+
"v_slope": v_slope,
|
|
1418
|
+
"side_slope": side_slope,
|
|
1419
|
+
"upstream_crest_height": upstream_crest_height,
|
|
1420
|
+
"downstream_crest_height": downstream_crest_height,
|
|
1421
|
+
"modular_limit": modular_limit,
|
|
1422
|
+
"calibration_coefficient": calibration_coefficient,
|
|
1423
|
+
"ds_face_slope": ds_face_slope,
|
|
1424
|
+
"coriolis_coefficient": coriolis_coefficient,
|
|
1425
|
+
"bank_top_elevation": bank_top_elevation,
|
|
1426
|
+
}.items():
|
|
1427
|
+
setattr(self, param, val)
|
|
1428
|
+
|
|
1429
|
+
|
|
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
|
+
class OUTFALL(Unit):
|
|
1583
|
+
"""Class to hold and process OUTFALL unit type
|
|
1584
|
+
|
|
1585
|
+
Args:
|
|
1586
|
+
name (str, optional): Unit name.
|
|
1587
|
+
comment (str, optional): Comment included in unit.
|
|
1588
|
+
flapped (bool, optional): ``True`` if outfall is flapped, ``False`` if outfall is open
|
|
1589
|
+
ds_label (str, optional): Downstream label
|
|
1590
|
+
invert (float, optional): Throat invert level
|
|
1591
|
+
soffit (float, optional): Throat soffit level
|
|
1592
|
+
bore_area (float, optional): Cross sectional area of throat opening
|
|
1593
|
+
upstream_sill (float, optional): Upstream sill level
|
|
1594
|
+
downstream_sill (float, optional): Downstream sill level
|
|
1595
|
+
shape (str, optional): Shape of outfall aperture ('RECTANGLE' or 'CIRCULAR')
|
|
1596
|
+
weir_flow (float, optional): Calibration factor for weir flow
|
|
1597
|
+
surcharged_flow (float, optional): Calibration factor for surcharged flow
|
|
1598
|
+
modular_limit (float, optional): Ratio of upstream and downstream heads when switching between free and drowned mode
|
|
1599
|
+
|
|
1600
|
+
|
|
1601
|
+
Returns:
|
|
1602
|
+
OUTFALL: Flood Modeller OUTFALL Unit class object
|
|
1603
|
+
"""
|
|
1604
|
+
|
|
1605
|
+
_unit = "OUTFALL"
|
|
1606
|
+
|
|
1607
|
+
def _read(self, block):
|
|
1608
|
+
"""Function to read a given OUTFALL block and store data as class attributes"""
|
|
1609
|
+
self._subtype = block[1].split(" ")[0].strip()
|
|
1610
|
+
self.flapped = self.subtype == "FLAPPED"
|
|
1611
|
+
|
|
1612
|
+
# Extends label line to be correct length before splitting to pick up blank labels
|
|
1613
|
+
labels = split_n_char(f"{block[2]:<{2*self._label_len}}", self._label_len)
|
|
1614
|
+
self.name = labels[0]
|
|
1615
|
+
self.ds_label = labels[1]
|
|
1616
|
+
self.comment = block[0].replace("OUTFALL", "").strip()
|
|
1617
|
+
|
|
1618
|
+
# First parameter line
|
|
1619
|
+
params1 = split_10_char(f"{block[3]:<60}")
|
|
1620
|
+
self.invert = _to_float(params1[0])
|
|
1621
|
+
self.soffit = _to_float(params1[1])
|
|
1622
|
+
self.bore_area = _to_float(params1[2])
|
|
1623
|
+
self.upstream_sill = _to_float(params1[3])
|
|
1624
|
+
self.downstream_sill = _to_float(params1[4])
|
|
1625
|
+
self.shape = _to_str(params1[5], "RECTANGLE")
|
|
1626
|
+
|
|
1627
|
+
# Second parameter line
|
|
1628
|
+
params2 = split_10_char(block[4])
|
|
1629
|
+
self.weir_flow = _to_float(params2[0], 1.0)
|
|
1630
|
+
self.surcharged_flow = _to_float(params2[1], 1.0)
|
|
1631
|
+
self.modular_limit = _to_float(params2[2], 0.7)
|
|
1632
|
+
|
|
1633
|
+
def _write(self):
|
|
1634
|
+
"""Function to write a valid OUTFALL block"""
|
|
1635
|
+
_validate_unit(self) # Function to check the params are valid for CONDUIT unit
|
|
1636
|
+
header = "OUTFALL " + self.comment
|
|
1637
|
+
labels = join_n_char_ljust(self._label_len, self.name, self.ds_label)
|
|
1638
|
+
|
|
1639
|
+
self._subtype = "FLAPPED" if self.flapped else "OPEN"
|
|
1640
|
+
block = [header, self.subtype, labels]
|
|
1641
|
+
|
|
1642
|
+
# First parameter line
|
|
1643
|
+
params1 = join_10_char(
|
|
1644
|
+
self.invert,
|
|
1645
|
+
self.soffit,
|
|
1646
|
+
self.bore_area,
|
|
1647
|
+
self.upstream_sill,
|
|
1648
|
+
self.downstream_sill,
|
|
1649
|
+
self.shape,
|
|
1650
|
+
)
|
|
1651
|
+
|
|
1652
|
+
# Second parameter line
|
|
1653
|
+
params2 = join_10_char(self.weir_flow, self.surcharged_flow, self.modular_limit)
|
|
1654
|
+
|
|
1655
|
+
block.extend([params1, params2])
|
|
1656
|
+
|
|
1657
|
+
return block
|
|
1658
|
+
|
|
1659
|
+
def _create_from_blank( # noqa: PLR0913
|
|
1660
|
+
self,
|
|
1661
|
+
name="new_outfall",
|
|
1662
|
+
flapped=False,
|
|
1663
|
+
ds_label="",
|
|
1664
|
+
comment="",
|
|
1665
|
+
invert=0.0,
|
|
1666
|
+
soffit=0.0,
|
|
1667
|
+
bore_area=1.0,
|
|
1668
|
+
upstream_sill=0.0,
|
|
1669
|
+
downstream_sill=0.0,
|
|
1670
|
+
shape="RECTANGLE",
|
|
1671
|
+
weir_flow=1.0,
|
|
1672
|
+
surcharged_flow=1.0,
|
|
1673
|
+
modular_limit=0.7,
|
|
1674
|
+
):
|
|
1675
|
+
for param, val in {
|
|
1676
|
+
"name": name,
|
|
1677
|
+
"flapped": flapped,
|
|
1678
|
+
"ds_label": ds_label,
|
|
1679
|
+
"comment": comment,
|
|
1680
|
+
"invert": invert,
|
|
1681
|
+
"soffit": soffit,
|
|
1682
|
+
"bore_area": bore_area,
|
|
1683
|
+
"upstream_sill": upstream_sill,
|
|
1684
|
+
"downstream_sill": downstream_sill,
|
|
1685
|
+
"shape": shape,
|
|
1686
|
+
"weir_flow": weir_flow,
|
|
1687
|
+
"surcharged_flow": surcharged_flow,
|
|
1688
|
+
"modular_limit": modular_limit,
|
|
1689
|
+
}.items():
|
|
1690
|
+
setattr(self, param, val)
|