openswmm 5.3.0.dev0__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.
- openswmm/CMakeLists.txt +31 -0
- openswmm/__init__.py +42 -0
- openswmm/_openswmm.pyx +12 -0
- openswmm/data/__init__.py +0 -0
- openswmm/gym/__init__.py +0 -0
- openswmm/openswmm.pxd +10 -0
- openswmm/output/CMakeLists.txt +45 -0
- openswmm/output/__init__.pxd +1 -0
- openswmm/output/__init__.py +13 -0
- openswmm/output/_output.pyi +732 -0
- openswmm/output/_output.pyx +1557 -0
- openswmm/output/output.pxd +368 -0
- openswmm/solver/CMakeLists.txt +50 -0
- openswmm/solver/__init__.pxd +1 -0
- openswmm/solver/__init__.py +22 -0
- openswmm/solver/_solver.pyi +1012 -0
- openswmm/solver/_solver.pyx +1646 -0
- openswmm/solver/solver.pxd +356 -0
- openswmm-5.3.0.dev0.dist-info/METADATA +228 -0
- openswmm-5.3.0.dev0.dist-info/RECORD +36 -0
- openswmm-5.3.0.dev0.dist-info/WHEEL +5 -0
- openswmm-5.3.0.dev0.dist-info/licenses/LICENSE +12 -0
- openswmm-5.3.0.dev0.dist-info/top_level.txt +2 -0
- tests/.DS_Store +0 -0
- tests/__init__.py +3 -0
- tests/data/.DS_Store +0 -0
- tests/data/__init__.py +3 -0
- tests/data/output/__init__.py +22 -0
- tests/data/output/example_output_1.out +0 -0
- tests/data/output/json_time_series.pickle +0 -0
- tests/data/solver/__init__.py +17 -0
- tests/data/solver/non_existent_input_file.rpt +2387 -0
- tests/data/solver/site_drainage_example.inp +499 -0
- tests/data/solver/site_drainage_example.rpt +354 -0
- tests/test_swmm_solver.py +716 -0
- tests/test_swwm_output.py +1048 -0
|
@@ -0,0 +1,716 @@
|
|
|
1
|
+
# Description: Unit tests for the openswmmcore solver module.
|
|
2
|
+
# Created by: Caleb Buahin (EPA/ORD/CESER/WID)
|
|
3
|
+
# Created on: 2024-11-19
|
|
4
|
+
|
|
5
|
+
# python imports
|
|
6
|
+
import unittest
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
|
|
9
|
+
# third party imports
|
|
10
|
+
import os
|
|
11
|
+
import sys
|
|
12
|
+
|
|
13
|
+
# local imports
|
|
14
|
+
from .data import solver as example_solver_data
|
|
15
|
+
from openswmmcore import solver
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class TestSWMMSolver(unittest.TestCase):
|
|
19
|
+
|
|
20
|
+
def setUp(self):
|
|
21
|
+
self.swmm_test_datetime = datetime(year=2024, month=11, day=16, hour=13, minute=33, second=21)
|
|
22
|
+
self.swmm_test_double_datetime = 45612.564826389
|
|
23
|
+
|
|
24
|
+
self.site_drainage_inp = example_solver_data.SITE_DRAINAGE_EXAMPLE_INPUT_FILE
|
|
25
|
+
self.site_drainage_rpt = example_solver_data.SITE_DRAINAGE_EXAMPLE_INPUT_FILE.replace(".inp", ".rpt")
|
|
26
|
+
self.site_drainage_out = example_solver_data.SITE_DRAINAGE_EXAMPLE_INPUT_FILE.replace(".inp", ".out")
|
|
27
|
+
|
|
28
|
+
@staticmethod
|
|
29
|
+
def progress_callback(progress: float) -> None:
|
|
30
|
+
"""
|
|
31
|
+
Progress callback function for the SWMM solver
|
|
32
|
+
:param progress:
|
|
33
|
+
:return:
|
|
34
|
+
"""
|
|
35
|
+
assert 0 <= progress <= 1.0
|
|
36
|
+
|
|
37
|
+
def test_get_swmm_version(self):
|
|
38
|
+
"""
|
|
39
|
+
Test the version function of the SWMM solver
|
|
40
|
+
:return:
|
|
41
|
+
"""
|
|
42
|
+
version = solver.version()
|
|
43
|
+
self.assertEqual(version, 53000, "SWMM version retrieved successfully")
|
|
44
|
+
|
|
45
|
+
def test_swmm_encode_date(self):
|
|
46
|
+
"""
|
|
47
|
+
Test the encode_swmm_datetime function
|
|
48
|
+
:return:
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
swmm_datetime_encoded = solver.encode_swmm_datetime(dt=self.swmm_test_datetime)
|
|
52
|
+
self.assertAlmostEqual(swmm_datetime_encoded, self.swmm_test_double_datetime)
|
|
53
|
+
|
|
54
|
+
def test_swmm_decode_date(self):
|
|
55
|
+
"""
|
|
56
|
+
Test the decode_swmm_datetime function
|
|
57
|
+
:return:
|
|
58
|
+
"""
|
|
59
|
+
swmm_datetime = solver.decode_swmm_datetime(
|
|
60
|
+
swmm_datetime=self.swmm_test_double_datetime
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
self.assertEqual(swmm_datetime, self.swmm_test_datetime)
|
|
64
|
+
|
|
65
|
+
def test_run_solver(self):
|
|
66
|
+
"""
|
|
67
|
+
Run the SWMM solver to solve the example input file
|
|
68
|
+
|
|
69
|
+
:return:
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
if os.path.exists(self.site_drainage_rpt):
|
|
73
|
+
os.remove(self.site_drainage_rpt)
|
|
74
|
+
|
|
75
|
+
if os.path.exists(self.site_drainage_out):
|
|
76
|
+
os.remove(self.site_drainage_out)
|
|
77
|
+
|
|
78
|
+
error = solver.run_solver(
|
|
79
|
+
inp_file=self.site_drainage_inp,
|
|
80
|
+
rpt_file=self.site_drainage_rpt,
|
|
81
|
+
out_file=self.site_drainage_out,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
self.assertEqual(error, 0, "SWMM solver run successfully.")
|
|
85
|
+
|
|
86
|
+
# Assert output and report files were created
|
|
87
|
+
self.assertTrue(os.path.exists(self.site_drainage_rpt))
|
|
88
|
+
self.assertTrue(os.path.exists(self.site_drainage_out))
|
|
89
|
+
|
|
90
|
+
def test_run_solver_with_progress_callback(self):
|
|
91
|
+
"""
|
|
92
|
+
Run the SWMM solver to solve the example input file with progress callback
|
|
93
|
+
|
|
94
|
+
:return:
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
if os.path.exists(self.site_drainage_rpt):
|
|
98
|
+
os.remove(self.site_drainage_rpt)
|
|
99
|
+
|
|
100
|
+
if os.path.exists(self.site_drainage_out):
|
|
101
|
+
os.remove(self.site_drainage_out)
|
|
102
|
+
|
|
103
|
+
error = solver.run_solver(
|
|
104
|
+
inp_file=example_solver_data.SITE_DRAINAGE_EXAMPLE_INPUT_FILE,
|
|
105
|
+
rpt_file=example_solver_data.SITE_DRAINAGE_EXAMPLE_INPUT_FILE.replace(".inp", ".rpt"),
|
|
106
|
+
out_file=example_solver_data.SITE_DRAINAGE_EXAMPLE_INPUT_FILE.replace(".inp", ".out"),
|
|
107
|
+
swmm_progress_callback=self.progress_callback
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
self.assertEqual(error, 0, "SWMM solver with callbacks run successfully.")
|
|
111
|
+
|
|
112
|
+
# Assert output and report files were created
|
|
113
|
+
self.assertTrue(os.path.exists(self.site_drainage_rpt))
|
|
114
|
+
self.assertTrue(os.path.exists(self.site_drainage_out))
|
|
115
|
+
|
|
116
|
+
def test_run_solver_invalid_inp_file(self):
|
|
117
|
+
"""
|
|
118
|
+
Run the SWMM solver with an invalid input file path to test error handling
|
|
119
|
+
:return:
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
with self.assertRaises(Exception) as context:
|
|
123
|
+
report_file = example_solver_data.NON_EXISTENT_INPUT_FILE.replace(".inp", ".rpt")
|
|
124
|
+
output_file = example_solver_data.NON_EXISTENT_INPUT_FILE.replace(".inp", ".out")
|
|
125
|
+
|
|
126
|
+
solver.run_solver(
|
|
127
|
+
inp_file=example_solver_data.NON_EXISTENT_INPUT_FILE,
|
|
128
|
+
rpt_file=report_file,
|
|
129
|
+
out_file=output_file,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
self.assertIn('ERROR 303: cannot open input file.', str(context.exception))
|
|
133
|
+
|
|
134
|
+
def test_run_without_context_manager(self):
|
|
135
|
+
"""
|
|
136
|
+
Run the SWMM solver without a context manager
|
|
137
|
+
:return:
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
if os.path.exists(self.site_drainage_rpt):
|
|
141
|
+
os.remove(self.site_drainage_rpt)
|
|
142
|
+
|
|
143
|
+
if os.path.exists(self.site_drainage_out):
|
|
144
|
+
os.remove(self.site_drainage_out)
|
|
145
|
+
|
|
146
|
+
swmm_solver = solver.Solver(
|
|
147
|
+
inp_file=self.site_drainage_inp,
|
|
148
|
+
rpt_file=self.site_drainage_rpt,
|
|
149
|
+
out_file=self.site_drainage_out,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
swmm_solver.execute()
|
|
153
|
+
|
|
154
|
+
# Assert output and report files were created
|
|
155
|
+
self.assertTrue(os.path.exists(self.site_drainage_rpt))
|
|
156
|
+
self.assertTrue(os.path.exists(self.site_drainage_out))
|
|
157
|
+
|
|
158
|
+
def test_run_without_context_manager_step_by_step(self):
|
|
159
|
+
"""
|
|
160
|
+
Run the SWMM solver without a context manager and an invalid input file path to test error handling
|
|
161
|
+
:return:
|
|
162
|
+
"""
|
|
163
|
+
if os.path.exists(self.site_drainage_rpt):
|
|
164
|
+
os.remove(self.site_drainage_rpt)
|
|
165
|
+
|
|
166
|
+
if os.path.exists(self.site_drainage_out):
|
|
167
|
+
os.remove(self.site_drainage_out)
|
|
168
|
+
|
|
169
|
+
swmm_solver = solver.Solver(
|
|
170
|
+
inp_file=self.site_drainage_inp,
|
|
171
|
+
rpt_file=self.site_drainage_rpt,
|
|
172
|
+
out_file=self.site_drainage_out,
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
swmm_solver.initialize()
|
|
176
|
+
|
|
177
|
+
while swmm_solver.solver_state != solver.SolverState.FINISHED:
|
|
178
|
+
swmm_solver.step()
|
|
179
|
+
|
|
180
|
+
swmm_solver.finalize()
|
|
181
|
+
|
|
182
|
+
# Assert output and report files were created
|
|
183
|
+
self.assertTrue(os.path.exists(self.site_drainage_rpt))
|
|
184
|
+
self.assertTrue(os.path.exists(self.site_drainage_out))
|
|
185
|
+
|
|
186
|
+
def test_run_solver_with_context_manager(self):
|
|
187
|
+
"""
|
|
188
|
+
Run the SWMM solver with an invalid report file path to test error handling
|
|
189
|
+
:return:
|
|
190
|
+
"""
|
|
191
|
+
|
|
192
|
+
with solver.Solver(
|
|
193
|
+
inp_file=example_solver_data.SITE_DRAINAGE_EXAMPLE_INPUT_FILE,
|
|
194
|
+
rpt_file=example_solver_data.NON_EXISTENT_INPUT_FILE.replace(".inp", ".rpt"),
|
|
195
|
+
out_file=example_solver_data.SITE_DRAINAGE_EXAMPLE_INPUT_FILE.replace(".inp", ".out"),
|
|
196
|
+
) as swmm_solver:
|
|
197
|
+
|
|
198
|
+
swmm_solver.start()
|
|
199
|
+
|
|
200
|
+
for _ in swmm_solver:
|
|
201
|
+
pass
|
|
202
|
+
|
|
203
|
+
def test_solver_get_time_attributes(self):
|
|
204
|
+
"""
|
|
205
|
+
Test the get_start_date function of the SWMM solver
|
|
206
|
+
:return:
|
|
207
|
+
"""
|
|
208
|
+
with solver.Solver(
|
|
209
|
+
inp_file=self.site_drainage_inp,
|
|
210
|
+
rpt_file=self.site_drainage_rpt,
|
|
211
|
+
out_file=self.site_drainage_out
|
|
212
|
+
) as swmm_solver:
|
|
213
|
+
# Initialize the solver
|
|
214
|
+
swmm_solver.start()
|
|
215
|
+
|
|
216
|
+
start_date = swmm_solver.start_datetime
|
|
217
|
+
end_date = swmm_solver.end_datetime
|
|
218
|
+
report_start_date = swmm_solver.report_start_datetime
|
|
219
|
+
|
|
220
|
+
self.assertEqual(start_date, datetime(year=1998, month=1, day=1))
|
|
221
|
+
self.assertEqual(end_date, datetime(year=1998, month=1, day=1, hour=6))
|
|
222
|
+
self.assertEqual(report_start_date, datetime(year=1998, month=1, day=1))
|
|
223
|
+
|
|
224
|
+
def test_solver_set_time_attributes(self):
|
|
225
|
+
"""
|
|
226
|
+
Test the set_start_date function of the SWMM solver
|
|
227
|
+
:return:
|
|
228
|
+
"""
|
|
229
|
+
with solver.Solver(
|
|
230
|
+
inp_file=self.site_drainage_inp,
|
|
231
|
+
rpt_file=self.site_drainage_rpt,
|
|
232
|
+
out_file=self.site_drainage_out
|
|
233
|
+
) as swmm_solver:
|
|
234
|
+
# Initialize the solver
|
|
235
|
+
|
|
236
|
+
start_date = datetime(year=2000, month=1, day=2)
|
|
237
|
+
end_date = datetime(year=2000, month=1, day=2, hour=2)
|
|
238
|
+
report_start_date = datetime(year=2000, month=1, day=2)
|
|
239
|
+
|
|
240
|
+
swmm_solver.start_datetime = start_date
|
|
241
|
+
swmm_solver.end_datetime = end_date
|
|
242
|
+
swmm_solver.report_start_datetime = report_start_date
|
|
243
|
+
|
|
244
|
+
swmm_solver.start()
|
|
245
|
+
|
|
246
|
+
for i, t in enumerate(swmm_solver):
|
|
247
|
+
current_datetime = swmm_solver.current_datetime
|
|
248
|
+
self.assertTrue(start_date <= current_datetime <= end_date, "Current datetime is within the range")
|
|
249
|
+
|
|
250
|
+
def test_get_object_count(self):
|
|
251
|
+
"""
|
|
252
|
+
Test the get_object_count function of the SWMM solver
|
|
253
|
+
:return:
|
|
254
|
+
"""
|
|
255
|
+
with solver.Solver(
|
|
256
|
+
inp_file=self.site_drainage_inp,
|
|
257
|
+
rpt_file=self.site_drainage_rpt,
|
|
258
|
+
out_file=self.site_drainage_out
|
|
259
|
+
) as swmm_solver:
|
|
260
|
+
|
|
261
|
+
swmm_solver.start()
|
|
262
|
+
|
|
263
|
+
num_raingages = swmm_solver.get_object_count(solver.SWMMObjects.RAIN_GAGE)
|
|
264
|
+
num_subcatchments = swmm_solver.get_object_count(solver.SWMMObjects.SUBCATCHMENT)
|
|
265
|
+
num_nodes = swmm_solver.get_object_count(solver.SWMMObjects.NODE)
|
|
266
|
+
num_links = swmm_solver.get_object_count(solver.SWMMObjects.LINK)
|
|
267
|
+
num_aquifers = swmm_solver.get_object_count(solver.SWMMObjects.AQUIFER)
|
|
268
|
+
num_snowpacks = swmm_solver.get_object_count(solver.SWMMObjects.SNOWPACK)
|
|
269
|
+
num_hydrographs = swmm_solver.get_object_count(solver.SWMMObjects.UNIT_HYDROGRAPH)
|
|
270
|
+
num_lids = swmm_solver.get_object_count(solver.SWMMObjects.LID)
|
|
271
|
+
num_streets = swmm_solver.get_object_count(solver.SWMMObjects.STREET)
|
|
272
|
+
num_inlets = swmm_solver.get_object_count(solver.SWMMObjects.INLET)
|
|
273
|
+
num_transects = swmm_solver.get_object_count(solver.SWMMObjects.TRANSECT)
|
|
274
|
+
num_xsections = swmm_solver.get_object_count(solver.SWMMObjects.XSECTION_SHAPE)
|
|
275
|
+
num_controls = swmm_solver.get_object_count(solver.SWMMObjects.CONTROL_RULE)
|
|
276
|
+
num_pollutants = swmm_solver.get_object_count(solver.SWMMObjects.POLLUTANT)
|
|
277
|
+
num_landuses = swmm_solver.get_object_count(solver.SWMMObjects.LANDUSE)
|
|
278
|
+
num_curves = swmm_solver.get_object_count(solver.SWMMObjects.CURVE)
|
|
279
|
+
num_timeseries = swmm_solver.get_object_count(solver.SWMMObjects.TIMESERIES)
|
|
280
|
+
num_time_patterns = swmm_solver.get_object_count(solver.SWMMObjects.TIME_PATTERN)
|
|
281
|
+
|
|
282
|
+
self.assertEqual(num_raingages, 1)
|
|
283
|
+
self.assertEqual(num_subcatchments, 7)
|
|
284
|
+
self.assertEqual(num_nodes, 12)
|
|
285
|
+
self.assertEqual(num_links, 11)
|
|
286
|
+
self.assertEqual(num_aquifers, 0)
|
|
287
|
+
self.assertEqual(num_snowpacks, 0)
|
|
288
|
+
self.assertEqual(num_hydrographs, 0)
|
|
289
|
+
self.assertEqual(num_lids, 0)
|
|
290
|
+
self.assertEqual(num_streets, 0)
|
|
291
|
+
self.assertEqual(num_inlets, 0)
|
|
292
|
+
self.assertEqual(num_transects, 0)
|
|
293
|
+
self.assertEqual(num_xsections, 0)
|
|
294
|
+
self.assertEqual(num_controls, 0)
|
|
295
|
+
self.assertEqual(num_pollutants, 1)
|
|
296
|
+
self.assertEqual(num_landuses, 4)
|
|
297
|
+
self.assertEqual(num_curves, 0)
|
|
298
|
+
self.assertEqual(num_timeseries, 3)
|
|
299
|
+
self.assertEqual(num_time_patterns, 0)
|
|
300
|
+
|
|
301
|
+
with self.assertRaises(solver.SWMMSolverException) as context:
|
|
302
|
+
swmm_solver.get_object_count(solver.SWMMObjects.SYSTEM)
|
|
303
|
+
|
|
304
|
+
self.assertIn('API Error -999904: invalid object type.', str(context.exception))
|
|
305
|
+
|
|
306
|
+
def test_get_object_names(self):
|
|
307
|
+
"""
|
|
308
|
+
Test the get_object_names function of the SWMM solver
|
|
309
|
+
:return:
|
|
310
|
+
"""
|
|
311
|
+
|
|
312
|
+
with solver.Solver(
|
|
313
|
+
inp_file=self.site_drainage_inp,
|
|
314
|
+
rpt_file=self.site_drainage_rpt,
|
|
315
|
+
out_file=self.site_drainage_out,
|
|
316
|
+
) as swmm_solver:
|
|
317
|
+
swmm_solver.start()
|
|
318
|
+
|
|
319
|
+
raingage_names = swmm_solver.get_object_names(solver.SWMMObjects.RAIN_GAGE)
|
|
320
|
+
subcatchment_names = swmm_solver.get_object_names(solver.SWMMObjects.SUBCATCHMENT)
|
|
321
|
+
node_names = swmm_solver.get_object_names(solver.SWMMObjects.NODE)
|
|
322
|
+
link_names = swmm_solver.get_object_names(solver.SWMMObjects.LINK)
|
|
323
|
+
pollutant_names = swmm_solver.get_object_names(solver.SWMMObjects.POLLUTANT)
|
|
324
|
+
landuse_names = swmm_solver.get_object_names(solver.SWMMObjects.LANDUSE)
|
|
325
|
+
timeseries_names = swmm_solver.get_object_names(solver.SWMMObjects.TIMESERIES)
|
|
326
|
+
|
|
327
|
+
self.assertListEqual(raingage_names, ['RainGage'])
|
|
328
|
+
self.assertListEqual(subcatchment_names, ['S1', 'S2', 'S3', 'S4', 'S5', 'S6', 'S7'])
|
|
329
|
+
self.assertListEqual(node_names, ['J1', 'J2', 'J3', 'J4', 'J5', 'J6', 'J7', 'J8', 'J9', 'J10', 'J11', 'O1'])
|
|
330
|
+
self.assertListEqual(link_names, ['C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9', 'C10', 'C11'])
|
|
331
|
+
self.assertListEqual(pollutant_names, ['TSS'])
|
|
332
|
+
self.assertListEqual(landuse_names, ['Residential_1', 'Residential_2', 'Commercial', 'Undeveloped'])
|
|
333
|
+
self.assertListEqual(timeseries_names, ['2-yr', '10-yr', '100-yr'])
|
|
334
|
+
|
|
335
|
+
def test_get_object_index(self):
|
|
336
|
+
"""
|
|
337
|
+
Test the get_object_index function of the SWMM solver
|
|
338
|
+
:return:
|
|
339
|
+
"""
|
|
340
|
+
|
|
341
|
+
with solver.Solver(
|
|
342
|
+
inp_file=self.site_drainage_inp,
|
|
343
|
+
rpt_file=self.site_drainage_rpt,
|
|
344
|
+
out_file=self.site_drainage_out,
|
|
345
|
+
) as swmm_solver:
|
|
346
|
+
swmm_solver.start()
|
|
347
|
+
|
|
348
|
+
rg_index = swmm_solver.get_object_index(solver.SWMMObjects.RAIN_GAGE, 'RainGage')
|
|
349
|
+
sc_index = swmm_solver.get_object_index(solver.SWMMObjects.SUBCATCHMENT, 'S2')
|
|
350
|
+
node_index = swmm_solver.get_object_index(solver.SWMMObjects.NODE, 'J6')
|
|
351
|
+
link_index = swmm_solver.get_object_index(solver.SWMMObjects.LINK, 'C10')
|
|
352
|
+
pollutant_index = swmm_solver.get_object_index(solver.SWMMObjects.POLLUTANT, 'TSS')
|
|
353
|
+
landuse_index = swmm_solver.get_object_index(solver.SWMMObjects.LANDUSE, 'Commercial')
|
|
354
|
+
timeseries_index = swmm_solver.get_object_index(solver.SWMMObjects.TIMESERIES, '10-yr')
|
|
355
|
+
|
|
356
|
+
self.assertEqual(rg_index, 0)
|
|
357
|
+
self.assertEqual(sc_index, 1)
|
|
358
|
+
self.assertEqual(node_index, 5)
|
|
359
|
+
self.assertEqual(link_index, 9)
|
|
360
|
+
self.assertEqual(pollutant_index, 0)
|
|
361
|
+
self.assertEqual(landuse_index, 2)
|
|
362
|
+
self.assertEqual(timeseries_index, 1)
|
|
363
|
+
|
|
364
|
+
def test_get_gage_value(self):
|
|
365
|
+
"""
|
|
366
|
+
Test the get_gage_value function of the SWMM solver
|
|
367
|
+
:return:
|
|
368
|
+
"""
|
|
369
|
+
|
|
370
|
+
with solver.Solver(
|
|
371
|
+
inp_file=self.site_drainage_inp,
|
|
372
|
+
rpt_file=self.site_drainage_rpt,
|
|
373
|
+
out_file=self.site_drainage_out,
|
|
374
|
+
) as swmm_solver:
|
|
375
|
+
swmm_solver.start()
|
|
376
|
+
|
|
377
|
+
for t in range(12):
|
|
378
|
+
swmm_solver.step()
|
|
379
|
+
|
|
380
|
+
rg_value = swmm_solver.get_value(
|
|
381
|
+
object_type=solver.SWMMObjects.RAIN_GAGE,
|
|
382
|
+
property_type=solver.SWMMRainGageProperties.GAGE_TOTAL_PRECIPITATION,
|
|
383
|
+
index=0,
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
self.assertAlmostEqual(rg_value / 12.0, 0.3)
|
|
387
|
+
|
|
388
|
+
def test_set_gage_value(self):
|
|
389
|
+
"""
|
|
390
|
+
Test the set_gage_value function of the SWMM solver
|
|
391
|
+
:return:
|
|
392
|
+
"""
|
|
393
|
+
|
|
394
|
+
with solver.Solver(
|
|
395
|
+
inp_file=self.site_drainage_inp,
|
|
396
|
+
rpt_file=self.site_drainage_rpt,
|
|
397
|
+
out_file=self.site_drainage_out,
|
|
398
|
+
) as swmm_solver:
|
|
399
|
+
swmm_solver.start()
|
|
400
|
+
|
|
401
|
+
swmm_solver.set_value(
|
|
402
|
+
object_type=solver.SWMMObjects.RAIN_GAGE,
|
|
403
|
+
property_type=solver.SWMMRainGageProperties.GAGE_RAINFALL,
|
|
404
|
+
index=0,
|
|
405
|
+
value=3.6
|
|
406
|
+
)
|
|
407
|
+
|
|
408
|
+
for _ in range(12):
|
|
409
|
+
swmm_solver.step()
|
|
410
|
+
|
|
411
|
+
rg_value = swmm_solver.get_value(
|
|
412
|
+
object_type=solver.SWMMObjects.RAIN_GAGE,
|
|
413
|
+
property_type=solver.SWMMRainGageProperties.GAGE_TOTAL_PRECIPITATION,
|
|
414
|
+
index=0,
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
self.assertAlmostEqual(rg_value, 3.6)
|
|
418
|
+
|
|
419
|
+
def test_get_sub_catchment_value(self):
|
|
420
|
+
"""
|
|
421
|
+
Test the get_subcatchment_value function of the SWMM solver
|
|
422
|
+
:return:
|
|
423
|
+
"""
|
|
424
|
+
|
|
425
|
+
with solver.Solver(
|
|
426
|
+
inp_file=self.site_drainage_inp,
|
|
427
|
+
rpt_file=self.site_drainage_rpt,
|
|
428
|
+
out_file=self.site_drainage_out,
|
|
429
|
+
) as swmm_solver:
|
|
430
|
+
swmm_solver.start()
|
|
431
|
+
|
|
432
|
+
for t in range(12):
|
|
433
|
+
swmm_solver.step()
|
|
434
|
+
|
|
435
|
+
sc_value = swmm_solver.get_value(
|
|
436
|
+
object_type=solver.SWMMObjects.SUBCATCHMENT,
|
|
437
|
+
property_type=solver.SWMMSubcatchmentProperties.RUNOFF,
|
|
438
|
+
index=1,
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
self.assertAlmostEqual(sc_value, 17.527141504933294)
|
|
442
|
+
|
|
443
|
+
def test_set_sub_catchment_value(self):
|
|
444
|
+
"""
|
|
445
|
+
Test the set_subcatchment_value function of the SWMM solver
|
|
446
|
+
:return:
|
|
447
|
+
"""
|
|
448
|
+
|
|
449
|
+
with solver.Solver(
|
|
450
|
+
inp_file=self.site_drainage_inp,
|
|
451
|
+
rpt_file=self.site_drainage_rpt,
|
|
452
|
+
out_file=self.site_drainage_out,
|
|
453
|
+
) as swmm_solver:
|
|
454
|
+
|
|
455
|
+
swmm_solver.set_value(
|
|
456
|
+
object_type=solver.SWMMObjects.SUBCATCHMENT,
|
|
457
|
+
property_type=solver.SWMMSubcatchmentProperties.WIDTH,
|
|
458
|
+
index=1,
|
|
459
|
+
value=100.0
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
swmm_solver.start()
|
|
463
|
+
|
|
464
|
+
for _ in range(12):
|
|
465
|
+
swmm_solver.step()
|
|
466
|
+
|
|
467
|
+
sc_value = swmm_solver.get_value(
|
|
468
|
+
object_type=solver.SWMMObjects.SUBCATCHMENT,
|
|
469
|
+
property_type=solver.SWMMSubcatchmentProperties.WIDTH,
|
|
470
|
+
index=1,
|
|
471
|
+
)
|
|
472
|
+
|
|
473
|
+
self.assertAlmostEqual(sc_value, 100.0)
|
|
474
|
+
|
|
475
|
+
def test_get_sub_catchment_initial_buildup(self):
|
|
476
|
+
"""
|
|
477
|
+
Test the get_subcatchment_initial_buildup function of the SWMM solver
|
|
478
|
+
|
|
479
|
+
:return:
|
|
480
|
+
"""
|
|
481
|
+
|
|
482
|
+
with solver.Solver(
|
|
483
|
+
inp_file=self.site_drainage_inp,
|
|
484
|
+
rpt_file=self.site_drainage_rpt,
|
|
485
|
+
out_file=self.site_drainage_out,
|
|
486
|
+
) as swmm_solver:
|
|
487
|
+
swmm_solver.start()
|
|
488
|
+
|
|
489
|
+
sc_value = swmm_solver.get_value(
|
|
490
|
+
object_type=solver.SWMMObjects.SUBCATCHMENT,
|
|
491
|
+
property_type=solver.SWMMSubcatchmentProperties.POLLUTANT_BUILDUP,
|
|
492
|
+
index=0,
|
|
493
|
+
sub_index=0,
|
|
494
|
+
)
|
|
495
|
+
|
|
496
|
+
self.assertEqual(first=sc_value, second=80.0)
|
|
497
|
+
|
|
498
|
+
def test_set_sub_catchment_initial_buildup(self):
|
|
499
|
+
"""
|
|
500
|
+
Test the get_subcatchment_initial_buildup function of the SWMM solver
|
|
501
|
+
|
|
502
|
+
:return:
|
|
503
|
+
"""
|
|
504
|
+
|
|
505
|
+
# import matplotlib
|
|
506
|
+
# matplotlib.use('TkAgg')
|
|
507
|
+
#
|
|
508
|
+
# import matplotlib.pyplot as plt
|
|
509
|
+
# import pandas as pd
|
|
510
|
+
#
|
|
511
|
+
# fig, axes = plt.subplots(nrows=2, ncols=1 , sharex=True)
|
|
512
|
+
|
|
513
|
+
with solver.Solver(
|
|
514
|
+
inp_file=self.site_drainage_inp,
|
|
515
|
+
rpt_file=self.site_drainage_rpt,
|
|
516
|
+
out_file=self.site_drainage_out,
|
|
517
|
+
) as swmm_solver:
|
|
518
|
+
|
|
519
|
+
swmm_solver.stride_step = 10000
|
|
520
|
+
|
|
521
|
+
swmm_solver.start()
|
|
522
|
+
|
|
523
|
+
for _ in swmm_solver:
|
|
524
|
+
pass
|
|
525
|
+
|
|
526
|
+
from openswmmcore import output
|
|
527
|
+
toutput = output.Output(output_file=self.site_drainage_out)
|
|
528
|
+
|
|
529
|
+
runoff = toutput.get_subcatchment_timeseries(
|
|
530
|
+
element_index='S1',
|
|
531
|
+
attribute=output.SubcatchAttribute.INFILTRATION_LOSS,
|
|
532
|
+
sub_index=0
|
|
533
|
+
)
|
|
534
|
+
|
|
535
|
+
results = toutput.get_subcatchment_timeseries(
|
|
536
|
+
element_index='S1',
|
|
537
|
+
attribute=output.SubcatchAttribute.POLLUTANT_CONCENTRATION,
|
|
538
|
+
sub_index=1
|
|
539
|
+
)
|
|
540
|
+
del toutput
|
|
541
|
+
|
|
542
|
+
# runoff = pd.Series(runoff, index=pd.to_datetime(list(runoff.keys())))
|
|
543
|
+
# runoff = pd.DataFrame(runoff, columns=['Runoff (cfs)'])
|
|
544
|
+
#
|
|
545
|
+
# runoff.plot()
|
|
546
|
+
# plt.show()
|
|
547
|
+
# matplotlib.use('TkAgg')
|
|
548
|
+
#
|
|
549
|
+
# runoff.plot(ax=axes[0])
|
|
550
|
+
|
|
551
|
+
# data = pd.Series(results, index=pd.to_datetime(list(results.keys())))
|
|
552
|
+
# data = pd.DataFrame(data, columns=['TSS Original (mg/L)'])
|
|
553
|
+
# data.plot(ax=axes[1], linewidth=3.0)
|
|
554
|
+
|
|
555
|
+
with solver.Solver(
|
|
556
|
+
inp_file=self.site_drainage_inp,
|
|
557
|
+
rpt_file=self.site_drainage_rpt,
|
|
558
|
+
out_file=self.site_drainage_out,
|
|
559
|
+
) as swmm_solver:
|
|
560
|
+
|
|
561
|
+
swmm_solver.start()
|
|
562
|
+
|
|
563
|
+
for t, elapsed_time in enumerate(swmm_solver):
|
|
564
|
+
|
|
565
|
+
if t == 10:
|
|
566
|
+
swmm_solver.set_value(
|
|
567
|
+
object_type=solver.SWMMObjects.SUBCATCHMENT,
|
|
568
|
+
property_type=solver.SWMMSubcatchmentProperties.EXTERNAL_POLLUTANT_BUILDUP,
|
|
569
|
+
index='S1',
|
|
570
|
+
value=120.0,
|
|
571
|
+
sub_index=0,
|
|
572
|
+
)
|
|
573
|
+
swmm_solver.step(1)
|
|
574
|
+
swmm_solver.set_value(
|
|
575
|
+
object_type=solver.SWMMObjects.SUBCATCHMENT,
|
|
576
|
+
property_type=solver.SWMMSubcatchmentProperties.EXTERNAL_POLLUTANT_BUILDUP,
|
|
577
|
+
index='S1',
|
|
578
|
+
value=0.0,
|
|
579
|
+
sub_index=0,
|
|
580
|
+
)
|
|
581
|
+
else:
|
|
582
|
+
pass
|
|
583
|
+
|
|
584
|
+
toutput = output.Output(output_file=self.site_drainage_out)
|
|
585
|
+
results = toutput.get_subcatchment_timeseries(
|
|
586
|
+
element_index='S1',
|
|
587
|
+
attribute=output.SubcatchAttribute.POLLUTANT_CONCENTRATION,
|
|
588
|
+
sub_index=1
|
|
589
|
+
)
|
|
590
|
+
del toutput
|
|
591
|
+
|
|
592
|
+
# rdata = pd.Series(results, index=pd.to_datetime(list(results.keys())))
|
|
593
|
+
# rdata = pd.DataFrame(rdata, columns=['TSS Modified (mg/L)'])
|
|
594
|
+
# rdata.plot(ax=axes[1])
|
|
595
|
+
#
|
|
596
|
+
# plt.show()
|
|
597
|
+
# matplotlib.use('TkAgg')
|
|
598
|
+
|
|
599
|
+
def test_get_node_value(self):
|
|
600
|
+
"""
|
|
601
|
+
Test the get_node_value function of the SWMM solver
|
|
602
|
+
:return:
|
|
603
|
+
"""
|
|
604
|
+
|
|
605
|
+
with solver.Solver(
|
|
606
|
+
inp_file=example_solver_data.SITE_DRAINAGE_EXAMPLE_INPUT_FILE,
|
|
607
|
+
rpt_file=example_solver_data.NON_EXISTENT_INPUT_FILE.replace(".inp", ".rpt"),
|
|
608
|
+
out_file=example_solver_data.SITE_DRAINAGE_EXAMPLE_INPUT_FILE.replace(".inp", ".out"),
|
|
609
|
+
) as swmm_solver:
|
|
610
|
+
swmm_solver.start()
|
|
611
|
+
|
|
612
|
+
for t in range(12):
|
|
613
|
+
swmm_solver.step()
|
|
614
|
+
|
|
615
|
+
node_value = swmm_solver.get_value(
|
|
616
|
+
object_type=solver.SWMMObjects.NODE,
|
|
617
|
+
property_type=solver.SWMMNodeProperties.TOTAL_INFLOW,
|
|
618
|
+
index=5,
|
|
619
|
+
)
|
|
620
|
+
|
|
621
|
+
self.assertAlmostEqual(node_value, 58.58717843671191)
|
|
622
|
+
|
|
623
|
+
def test_set_node_value(self):
|
|
624
|
+
"""
|
|
625
|
+
Test the set_node_value function of the SWMM solver
|
|
626
|
+
:return:
|
|
627
|
+
"""
|
|
628
|
+
|
|
629
|
+
with solver.Solver(
|
|
630
|
+
inp_file=example_solver_data.SITE_DRAINAGE_EXAMPLE_INPUT_FILE,
|
|
631
|
+
rpt_file=example_solver_data.NON_EXISTENT_INPUT_FILE.replace(".inp", ".rpt"),
|
|
632
|
+
out_file=example_solver_data.SITE_DRAINAGE_EXAMPLE_INPUT_FILE.replace(".inp", ".out"),
|
|
633
|
+
) as swmm_solver:
|
|
634
|
+
|
|
635
|
+
swmm_solver.set_value(
|
|
636
|
+
object_type=solver.SWMMObjects.NODE,
|
|
637
|
+
property_type=solver.SWMMNodeProperties.INVERT_ELEVATION,
|
|
638
|
+
index=5,
|
|
639
|
+
value=10.0
|
|
640
|
+
)
|
|
641
|
+
|
|
642
|
+
swmm_solver.start()
|
|
643
|
+
|
|
644
|
+
for _ in range(12):
|
|
645
|
+
swmm_solver.step()
|
|
646
|
+
|
|
647
|
+
node_value = swmm_solver.get_value(
|
|
648
|
+
object_type=solver.SWMMObjects.NODE,
|
|
649
|
+
property_type=solver.SWMMNodeProperties.INVERT_ELEVATION,
|
|
650
|
+
index=5,
|
|
651
|
+
)
|
|
652
|
+
|
|
653
|
+
self.assertAlmostEqual(node_value, 10.0)
|
|
654
|
+
|
|
655
|
+
def test_get_link_value(self):
|
|
656
|
+
"""
|
|
657
|
+
Test the get_link_value function of the SWMM solver
|
|
658
|
+
:return:
|
|
659
|
+
"""
|
|
660
|
+
|
|
661
|
+
with solver.Solver(
|
|
662
|
+
inp_file=example_solver_data.SITE_DRAINAGE_EXAMPLE_INPUT_FILE,
|
|
663
|
+
rpt_file=example_solver_data.NON_EXISTENT_INPUT_FILE.replace(".inp", ".rpt"),
|
|
664
|
+
out_file=example_solver_data.SITE_DRAINAGE_EXAMPLE_INPUT_FILE.replace(".inp", ".out"),
|
|
665
|
+
) as swmm_solver:
|
|
666
|
+
swmm_solver.start()
|
|
667
|
+
|
|
668
|
+
for t in range(12):
|
|
669
|
+
swmm_solver.step()
|
|
670
|
+
|
|
671
|
+
link_value = swmm_solver.get_value(
|
|
672
|
+
object_type=solver.SWMMObjects.LINK,
|
|
673
|
+
property_type=solver.SWMMLinkProperties.FLOW,
|
|
674
|
+
index=9,
|
|
675
|
+
)
|
|
676
|
+
|
|
677
|
+
link_value_by_name = swmm_solver.get_value(
|
|
678
|
+
object_type=solver.SWMMObjects.LINK,
|
|
679
|
+
property_type=solver.SWMMLinkProperties.FLOW,
|
|
680
|
+
index='C10',
|
|
681
|
+
)
|
|
682
|
+
|
|
683
|
+
self.assertAlmostEqual(first=link_value, second=102.01283173880869)
|
|
684
|
+
self.assertAlmostEqual(first=link_value, second=link_value_by_name)
|
|
685
|
+
|
|
686
|
+
def test_set_link_value(self):
|
|
687
|
+
"""
|
|
688
|
+
Test the set_link_value function of the SWMM solver
|
|
689
|
+
:return:
|
|
690
|
+
"""
|
|
691
|
+
|
|
692
|
+
with solver.Solver(
|
|
693
|
+
inp_file=example_solver_data.SITE_DRAINAGE_EXAMPLE_INPUT_FILE,
|
|
694
|
+
rpt_file=example_solver_data.NON_EXISTENT_INPUT_FILE.replace(".inp", ".rpt"),
|
|
695
|
+
out_file=example_solver_data.SITE_DRAINAGE_EXAMPLE_INPUT_FILE.replace(".inp", ".out"),
|
|
696
|
+
) as swmm_solver:
|
|
697
|
+
|
|
698
|
+
swmm_solver.set_value(
|
|
699
|
+
object_type=solver.SWMMObjects.LINK,
|
|
700
|
+
property_type=solver.SWMMLinkProperties.START_NODE_OFFSET,
|
|
701
|
+
index=9,
|
|
702
|
+
value=1.0
|
|
703
|
+
)
|
|
704
|
+
|
|
705
|
+
swmm_solver.start()
|
|
706
|
+
|
|
707
|
+
for _ in range(12):
|
|
708
|
+
swmm_solver.step()
|
|
709
|
+
|
|
710
|
+
link_value = swmm_solver.get_value(
|
|
711
|
+
object_type=solver.SWMMObjects.LINK,
|
|
712
|
+
property_type=solver.SWMMLinkProperties.START_NODE_OFFSET,
|
|
713
|
+
index=9,
|
|
714
|
+
)
|
|
715
|
+
|
|
716
|
+
self.assertAlmostEqual(link_value, 1.0)
|