-
Notifications
You must be signed in to change notification settings - Fork 1
/
swmm5_iface.bas
325 lines (277 loc) · 10.3 KB
/
swmm5_iface.bas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
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
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
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
323
324
325
Attribute VB_Name = "Module2"
' SWMM5_IFACE.BAS
'
' Example code for interfacing SWMM 5
' with Visual Basic Applications
'
' Remember to add SWMM5.BAS to the application
Private Type STARTUPINFO
cb As Long
lpReserved As String
lpDesktop As String
lpTitle As String
dwX As Long
dwY As Long
dwXSize As Long
dwYSize As Long
dwXCountChars As Long
dwYCountChars As Long
dwFillAttribute As Long
dwFlags As Long
wShowWindow As Integer
cbReserved2 As Integer
lpReserved2 As Long
hStdInput As Long
hStdOutput As Long
hStdError As Long
End Type
Private Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessID As Long
dwThreadID As Long
End Type
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal _
hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CreateProcessA Lib "kernel32" (ByVal _
lpApplicationName As String, ByVal lpCommandLine As String, ByVal _
lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, _
lpStartupInfo As STARTUPINFO, lpProcessInformation As _
PROCESS_INFORMATION) As Long
Private Declare Function CloseHandle Lib "kernel32" _
(ByVal hObject As Long) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As Long, lpExitCode As Long) As Long
Private Const SUBCATCH = 0
Private Const NODE = 1
Private Const LINK = 2
Private Const SYS = 3
Private Const INFINITE = -1&
Private Const SW_SHOWNORMAL = 1&
Private Const RECORDSIZE = 4 ' number of bytes per file record
Private SubcatchVars As Long ' number of subcatch reporting variable
Private NodeVars As Long ' number of node reporting variables
Private LinkVars As Long ' number of link reporting variables
Private SysVars As Long ' number of system reporting variables
Private Fout As Integer ' file handle
Private StartPos As Long ' file position where results start
Private BytesPerPeriod As Long ' number of bytes used for storing
' results in file each reporting period
Public SWMM_Nperiods As Long ' number of reporting periods
Public SWMM_FlowUnits As Long ' flow units code
Public SWMM_Nsubcatch As Long ' number of subcatchments
Public SWMM_Nnodes As Long ' number of drainage system nodes
Public SWMM_Nlinks As Long ' number of drainage system links
Public SWMM_Npolluts As Long ' number of pollutants tracked
Public SWMM_StartDate As Double ' start date of simulation
Public SWMM_ReportStep As Long ' reporting time step (seconds)
Public Function RunSwmmExe(cmdLine As String) As Long
'------------------------------------------------------------------------------
' Input: cmdLine = command line for running the console version of SWMM 5
' Output: returns the exit code generated by running SWMM5.EXE
' Purpose: runs the command line version of SWMM 5.
'------------------------------------------------------------------------------
Dim pi As PROCESS_INFORMATION
Dim si As STARTUPINFO
Dim exitCode As Long
' --- Initialize data structures
si.cb = Len(si)
si.wShowWindow = SW_SHOWNORMAL
' --- launch swmm5.exe
exitCode = CreateProcessA(vbNullString, cmdLine, 0&, 0&, 0&, _
0&, 0&, vbNullString, si, pi)
' --- wait for program to end
exitCode = WaitForSingleObject(pi.hProcess, INFINITE)
' --- retrieve the error code produced by the program
Call GetExitCodeProcess(proc.hProcess, exitCode)
' --- release handles
Call CloseHandle(pi.hThread)
Call CloseHandle(pi.hProcess)
RunSwmmExe = exitCode
End Function
Public Function RunSwmmDll(inpFile As String, rptFile As String, _
OutFile As String) As Long
'------------------------------------------------------------------------------
' Input: inpFile = name of SWMM 5 input file
' rptFile = name of status report file
' outFile = name of binary output file
' Output: returns a SWMM 5 error code or 0 if there are no errors
' Purpose: runs the dynamic link library version of SWMM 5.
'------------------------------------------------------------------------------
Dim err As Long
Dim elapsedTime As Double
' --- open a SWMM project
err = swmm_open(inpFile, rptFile, OutFile)
If err = 0 Then
' --- initialize all processing systems
err = swmm_start(1)
If err = 0 Then
' --- step through the simulation
Do
' --- allow Windows to process any pending events
DoEvents
' --- extend the simulation by one routing time step
err = swmm_step(elapsedTime)
'//////////////////////////////////////////
' call a progress reporting function here,
' using elapsedTime as an argument
'//////////////////////////////////////////
Loop While elapsedTime > 0# And err = 0
End If
' --- close all processing systems
swmm_end
End If
' --- close the project
swmm_close
' --- return the error code
RunSwmmDll = err
End Function
Function OpenSwmmOutFile(OutFile As String) As Long
'------------------------------------------------------------------------------
' Input: outFile = name of binary output file
' Output: returns 0 if successful, 1 if binary file invalid because
' SWMM 5 ran with errors, or 2 if the file cannot be opened
' Purpose: opens the binary output file created by a SWMM 5 run and
' retrieves the following simulation data that can be
' accessed by the application:
' SWMM_Nperiods = number of reporting periods
' SWMM_FlowUnits = flow units code
' SWMM_Nsubcatch = number of subcatchments
' SWMM_Nnodes = number of drainage system nodes
' SWMM_Nlinks = number of drainage system links
' SWMM_Npolluts = number of pollutants tracked
' SWMM_StartDate = start date of simulation
' SWMM_ReportStep = reporting time step (seconds)
'------------------------------------------------------------------------------
Dim magic1 As Long
Dim magic2 As Long
Dim errCode As Long
Dim version As Long
Dim offset As Long
Dim offset0 As Long
Dim err As Long
' --- open the output file
On Error GoTo FINISH
err = 2
Fout = FreeFile
Open OutFile For Binary Access Read As #Fout
' --- check that file contains at least 14 records
If LOF(1) < 14 * RECORDSIZE Then
OpenOutFile = 1
Close Fout
Exit Function
End If
' --- read parameters from end of file
Seek #Fout, LOF(Fout) - 5 * RECORDSIZE + 1
Get #Fout, , offset0
Get #Fout, , StartPos
Get #Fout, , SWMM_Nperiods
Get #Fout, , errCode
Get #Fout, , magic2
' --- read magic number from beginning of file
Seek #Fout, 1
Get #Fout, , magic1
' --- perform error checks
If magic1 <> magic2 Then
err = 1
ElseIf errCode <> 0 Then
err = 1
ElseIf SWMM_Nperiods = 0 Then
err = 1
Else
err = 0
End If
' --- quit if errors found
If err > 0 Then
Close (Fout)
OpenOutFile = err
Exit Function
End If
' --- otherwise read additional parameters from start of file
Get #Fout, , version
Get #Fout, , SWMM_FlowUnits
Get #Fout, , SWMM_Nsubcatch
Get #Fout, , SWMM_Nnodes
Get #Fout, , SWMM_Nlinks
Get #Fout, , SWMM_Npolluts
' --- skip over saved subcatch/node/link input values
offset = (SWMM_Nsubcatch + 2) * RECORDSIZE
offset = offset + (3 * SWMM_Nnodes + 4) * RECORDSIZE
offset = offset + (5 * SWMM_Nlinks + 6) * RECORDSIZE
offset = offset0 + offset + 1
Seek #Fout, offset
' --- read number & codes of computed variables
Get #Fout, , SubcatchVars
Seek #Fout, Seek(Fout) + (SubcatchVars * RECORDSIZE)
Get #Fout, , NodeVars
Seek #Fout, Seek(Fout) + (NodeVars * RECORDSIZE)
Get #Fout, , LinkVars
Seek #Fout, Seek(Fout) + (LinkVars * RECORDSIZE)
Get #Fout, , SysVars
' --- read data just before start of output results
Seek #Fout, StartPos - 3 * RECORDSIZE + 1
Get #Fout, , SWMM_StartDate
Get #Fout, , SWMM_ReportStep
' --- compute number of bytes stored per reporting period
BytesPerPeriod = RECORDSIZE * 2
BytesPerPeriod = BytesPerPeriod + RECORDSIZE * SWMM_Nsubcatch * SubcatchVars
BytesPerPeriod = BytesPerPeriod + RECORDSIZE * SWMM_Nnodes * NodeVars
BytesPerPeriod = BytesPerPeriod + RECORDSIZE * SWMM_Nlinks * LinkVars
BytesPerPeriod = BytesPerPeriod + RECORDSIZE * SysVars
' --- return with file left open
OpenSwmmOutFile = err
Exit Function
' --- error handler
FINISH:
OpenSwmmOutFile = err
Close (Fout)
End Function
Function GetSwmmResult(ByVal iType As Long, ByVal iIndex As Long, _
ByVal vIndex As Long, ByVal period As Long, Value As Single) As Integer
'------------------------------------------------------------------------------
' Input: iType = type of object whose value is being sought
' (0 = subcatchment, 1 = node, 2 = link, 3 = system
' iIndex = index of item being sought (starting from 0)
' vIndex = index of variable being sought (see Interfacing Guide)
' period = reporting period index (starting from 1)
' Output: value = value of variable being sought;
' function returns 1 if successful, 0 if not
' Purpose: finds the result of a specific variable for a given object
' at a specified time period.
'------------------------------------------------------------------------------
Dim offset As Long
Dim offset1 As Long
Dim offset2 As Long
Dim X As Single
'// --- compute offset into output file
Value = 0#
GetSwmmResult = 0
offset1 = StartPos + (period - 1) * BytesPerPeriod + 2 * RECORDSIZE + 1
offset2 = 0
If iType = SUBCATCH Then
offset2 = iIndex * SubcatchVars + vIndex
ElseIf iType = NODE Then
offset2 = SWMM_Nsubcatch * SubcatchVars + iIndex * NodeVars + vIndex
ElseIf iType = LINK Then
offset2 = SWMM_Nsubcatch * SubctchVars + SWMM_Nnodes * NodeVars + iIndex * LinkVars + vIndex
ElseIf iType = SYS Then
offset2 = SWMM_Nsubcatch * SubcatchVars + SWMM_Nnodes * NodeVars + SWMM_Nlinks * LinkVars + vIndex
Else: Exit Function
End If
'// --- re-position the file and read result
offset = offset1 + RECORDSIZE * offset2
Seek #Fout, offset
Get #Fout, , X
Value = X
GetSwmmResult = 1
End Function
Public Sub CloseSwmmOutFile()
'------------------------------------------------------------------------------
' Input: none
' Output: none
' Purpose: closes the binary output file.
'------------------------------------------------------------------------------
Close (Fout)
End Sub