epyt-flow 0.14.2__py3-none-any.whl → 0.15.0b1__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.
Files changed (102) hide show
  1. epyt_flow/VERSION +1 -1
  2. epyt_flow/__init__.py +0 -37
  3. epyt_flow/data/benchmarks/battledim.py +2 -2
  4. epyt_flow/data/benchmarks/leakdb.py +12 -9
  5. epyt_flow/gym/scenario_control_env.py +32 -33
  6. epyt_flow/simulation/events/actuator_events.py +24 -18
  7. epyt_flow/simulation/events/leakages.py +59 -57
  8. epyt_flow/simulation/events/quality_events.py +21 -30
  9. epyt_flow/simulation/events/system_event.py +3 -3
  10. epyt_flow/simulation/scada/complex_control.py +14 -12
  11. epyt_flow/simulation/scada/custom_control.py +22 -21
  12. epyt_flow/simulation/scada/scada_data.py +107 -104
  13. epyt_flow/simulation/scada/simple_control.py +38 -31
  14. epyt_flow/simulation/scenario_simulator.py +367 -395
  15. epyt_flow/simulation/sensor_config.py +31 -32
  16. epyt_flow/topology.py +11 -10
  17. epyt_flow/uncertainty/model_uncertainty.py +146 -122
  18. epyt_flow/utils.py +0 -66
  19. epyt_flow/visualization/visualization_utils.py +2 -4
  20. {epyt_flow-0.14.2.dist-info → epyt_flow-0.15.0b1.dist-info}/METADATA +12 -18
  21. epyt_flow-0.15.0b1.dist-info/RECORD +65 -0
  22. epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS +0 -28
  23. epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +0 -21
  24. epyt_flow/EPANET/EPANET/SRC_engines/Readme_SRC_Engines.txt +0 -18
  25. epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +0 -134
  26. epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +0 -5578
  27. epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +0 -865
  28. epyt_flow/EPANET/EPANET/SRC_engines/epanet2.def +0 -131
  29. epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +0 -73
  30. epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +0 -193
  31. epyt_flow/EPANET/EPANET/SRC_engines/genmmd.c +0 -1000
  32. epyt_flow/EPANET/EPANET/SRC_engines/hash.c +0 -177
  33. epyt_flow/EPANET/EPANET/SRC_engines/hash.h +0 -28
  34. epyt_flow/EPANET/EPANET/SRC_engines/hydcoeffs.c +0 -1151
  35. epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +0 -1117
  36. epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +0 -720
  37. epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +0 -476
  38. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +0 -431
  39. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +0 -1786
  40. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +0 -468
  41. epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +0 -810
  42. epyt_flow/EPANET/EPANET/SRC_engines/input1.c +0 -707
  43. epyt_flow/EPANET/EPANET/SRC_engines/input2.c +0 -864
  44. epyt_flow/EPANET/EPANET/SRC_engines/input3.c +0 -2170
  45. epyt_flow/EPANET/EPANET/SRC_engines/main.c +0 -93
  46. epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +0 -142
  47. epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +0 -24
  48. epyt_flow/EPANET/EPANET/SRC_engines/output.c +0 -852
  49. epyt_flow/EPANET/EPANET/SRC_engines/project.c +0 -1359
  50. epyt_flow/EPANET/EPANET/SRC_engines/quality.c +0 -685
  51. epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +0 -743
  52. epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +0 -694
  53. epyt_flow/EPANET/EPANET/SRC_engines/report.c +0 -1489
  54. epyt_flow/EPANET/EPANET/SRC_engines/rules.c +0 -1362
  55. epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +0 -871
  56. epyt_flow/EPANET/EPANET/SRC_engines/text.h +0 -497
  57. epyt_flow/EPANET/EPANET/SRC_engines/types.h +0 -874
  58. epyt_flow/EPANET/EPANET-MSX/MSX_Updates.txt +0 -53
  59. epyt_flow/EPANET/EPANET-MSX/Src/dispersion.h +0 -27
  60. epyt_flow/EPANET/EPANET-MSX/Src/hash.c +0 -107
  61. epyt_flow/EPANET/EPANET-MSX/Src/hash.h +0 -28
  62. epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx.h +0 -102
  63. epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx_export.h +0 -42
  64. epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.c +0 -937
  65. epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.h +0 -39
  66. epyt_flow/EPANET/EPANET-MSX/Src/mempool.c +0 -204
  67. epyt_flow/EPANET/EPANET-MSX/Src/mempool.h +0 -24
  68. epyt_flow/EPANET/EPANET-MSX/Src/msxchem.c +0 -1285
  69. epyt_flow/EPANET/EPANET-MSX/Src/msxcompiler.c +0 -368
  70. epyt_flow/EPANET/EPANET-MSX/Src/msxdict.h +0 -42
  71. epyt_flow/EPANET/EPANET-MSX/Src/msxdispersion.c +0 -586
  72. epyt_flow/EPANET/EPANET-MSX/Src/msxerr.c +0 -116
  73. epyt_flow/EPANET/EPANET-MSX/Src/msxfile.c +0 -260
  74. epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.c +0 -175
  75. epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.h +0 -35
  76. epyt_flow/EPANET/EPANET-MSX/Src/msxinp.c +0 -1504
  77. epyt_flow/EPANET/EPANET-MSX/Src/msxout.c +0 -401
  78. epyt_flow/EPANET/EPANET-MSX/Src/msxproj.c +0 -791
  79. epyt_flow/EPANET/EPANET-MSX/Src/msxqual.c +0 -2010
  80. epyt_flow/EPANET/EPANET-MSX/Src/msxrpt.c +0 -400
  81. epyt_flow/EPANET/EPANET-MSX/Src/msxtank.c +0 -422
  82. epyt_flow/EPANET/EPANET-MSX/Src/msxtoolkit.c +0 -1164
  83. epyt_flow/EPANET/EPANET-MSX/Src/msxtypes.h +0 -551
  84. epyt_flow/EPANET/EPANET-MSX/Src/msxutils.c +0 -524
  85. epyt_flow/EPANET/EPANET-MSX/Src/msxutils.h +0 -56
  86. epyt_flow/EPANET/EPANET-MSX/Src/newton.c +0 -158
  87. epyt_flow/EPANET/EPANET-MSX/Src/newton.h +0 -34
  88. epyt_flow/EPANET/EPANET-MSX/Src/rk5.c +0 -287
  89. epyt_flow/EPANET/EPANET-MSX/Src/rk5.h +0 -39
  90. epyt_flow/EPANET/EPANET-MSX/Src/ros2.c +0 -293
  91. epyt_flow/EPANET/EPANET-MSX/Src/ros2.h +0 -35
  92. epyt_flow/EPANET/EPANET-MSX/Src/smatrix.c +0 -816
  93. epyt_flow/EPANET/EPANET-MSX/Src/smatrix.h +0 -29
  94. epyt_flow/EPANET/EPANET-MSX/readme.txt +0 -14
  95. epyt_flow/EPANET/compile_linux.sh +0 -4
  96. epyt_flow/EPANET/compile_macos.sh +0 -4
  97. epyt_flow/simulation/backend/__init__.py +0 -1
  98. epyt_flow/simulation/backend/my_epyt.py +0 -1101
  99. epyt_flow-0.14.2.dist-info/RECORD +0 -142
  100. {epyt_flow-0.14.2.dist-info → epyt_flow-0.15.0b1.dist-info}/WHEEL +0 -0
  101. {epyt_flow-0.14.2.dist-info → epyt_flow-0.15.0b1.dist-info}/licenses/LICENSE +0 -0
  102. {epyt_flow-0.14.2.dist-info → epyt_flow-0.15.0b1.dist-info}/top_level.txt +0 -0
@@ -1,2170 +0,0 @@
1
- /*
2
- ******************************************************************************
3
- Project: OWA EPANET
4
- Version: 2.2
5
- Module: input3.c
6
- Description: parses network data from a line of an EPANET input file
7
- Authors: see AUTHORS
8
- Copyright: see AUTHORS
9
- License: see LICENSE
10
- Last Updated: 11/29/2019
11
- ******************************************************************************
12
- */
13
-
14
- #include <stdlib.h>
15
- #include <stdio.h>
16
- #include <string.h>
17
- #include <math.h>
18
-
19
- #include "types.h"
20
- #include "funcs.h"
21
- #include "hash.h"
22
- #include "text.h"
23
-
24
- // Defined in ENUMSTXT.H
25
- extern char *MixTxt[];
26
- extern char *Fldname[];
27
- extern char *DemandModelTxt[];
28
-
29
- // Exported functions
30
- int powercurve(double, double, double, double, double, double *, double *,
31
- double *);
32
-
33
- // Imported Functions
34
- extern int addnodeID(Network *, int, char *);
35
- extern int addlinkID(Network *, int, char *);
36
-
37
- // Local functions
38
- static int optionchoice(Project *, int);
39
- static int optionvalue(Project *, int);
40
- static int getpumpcurve(Project *, int);
41
- static void changestatus(Network *, int, StatusType, double);
42
- static int setError(Parser *, int, int);
43
-
44
-
45
- int setError(Parser *parser, int tokindex, int errcode)
46
- /*
47
- **--------------------------------------------------------------
48
- ** Input: tokindex = index of input line token
49
- ** errcode = an error code
50
- ** Output: returns error code
51
- ** Purpose: records index of token from line of input associated
52
- ** with an error
53
- **--------------------------------------------------------------
54
- */
55
- {
56
- parser->ErrTok = tokindex;
57
- return errcode;
58
- }
59
-
60
- int juncdata(Project *pr)
61
- /*
62
- **--------------------------------------------------------------
63
- ** Input: none
64
- ** Output: returns error code
65
- ** Purpose: processes junction data
66
- ** Format:
67
- ** [JUNCTIONS]
68
- ** id elev. (demand) (demand pattern)
69
- **--------------------------------------------------------------
70
- */
71
- {
72
- Network *net = &pr->network;
73
- Parser *parser = &pr->parser;
74
- Hydraul *hyd = &pr->hydraul;
75
-
76
- int p = 0; // time pattern index
77
- int n; // number of tokens
78
- int njuncs; // number of network junction nodes
79
- double el, // elevation
80
- y = 0.0; // base demand
81
- Snode *node;
82
- int err = 0;
83
-
84
- // Add new junction to data base
85
- n = parser->Ntokens;
86
- if (net->Nnodes == parser->MaxNodes) return 200;
87
- net->Njuncs++;
88
- net->Nnodes++;
89
- njuncs = net->Njuncs;
90
- err = addnodeID(net, net->Njuncs, parser->Tok[0]);
91
- if (err) return setError(parser, 0, err);
92
-
93
- // Check for valid data
94
- if (n < 2) return 201;
95
- if (!getfloat(parser->Tok[1], &el)) return setError(parser, 1, 202);
96
- if (n >= 3 && !getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
97
- if (n >= 4)
98
- {
99
- p = findpattern(net, parser->Tok[3]);
100
- if (p < 0) return setError(parser, 3, 205);
101
- }
102
-
103
- // Save junction data
104
- node = &net->Node[njuncs];
105
- node->X = MISSING;
106
- node->Y = MISSING;
107
- node->El = el;
108
- node->C0 = 0.0;
109
- node->S = NULL;
110
- node->Ke = 0.0;
111
- node->Rpt = 0;
112
- node->ResultIndex = 0;
113
- node->Type = JUNCTION;
114
- node->Comment = xstrcpy(&node->Comment, parser->Comment, MAXMSG);
115
-
116
- // Create a demand for the junction and use NodeDemand as an indicator
117
- // to be used when processing demands from the [DEMANDS] section
118
- if (!adddemand(node, y, p, NULL)) return 101;
119
- hyd->NodeDemand[njuncs] = y;
120
- return 0;
121
- }
122
-
123
- int tankdata(Project *pr)
124
- /*
125
- **--------------------------------------------------------------
126
- ** Input: none
127
- ** Output: returns error code
128
- ** Purpose: processes tank & reservoir data
129
- ** Format:
130
- ** [RESERVOIRS]
131
- ** id elev (pattern)
132
- ** [TANKS]
133
- ** id elev (pattern)
134
- ** id elev initlevel minlevel maxlevel diam (minvol vcurve)
135
- **--------------------------------------------------------------
136
- */
137
- {
138
- Network *net = &pr->network;
139
- Parser *parser = &pr->parser;
140
-
141
- int i, // Node index
142
- n, // # data items
143
- pattern = 0, // Time pattern index
144
- curve = 0, // Curve index
145
- overflow = FALSE;// Overflow indicator
146
-
147
- double el = 0.0, // Elevation
148
- initlevel = 0.0, // Initial level
149
- minlevel = 0.0, // Minimum level
150
- maxlevel = 0.0, // Maximum level
151
- minvol = 0.0, // Minimum volume
152
- diam = 0.0, // Diameter
153
- area; // X-sect. area
154
- Snode *node;
155
- Stank *tank;
156
-
157
- int err = 0;
158
-
159
- // Add new tank to data base
160
- n = parser->Ntokens;
161
- if (net->Ntanks == parser->MaxTanks ||
162
- net->Nnodes == parser->MaxNodes) return 200;
163
- net->Ntanks++;
164
- net->Nnodes++;
165
-
166
- i = parser->MaxJuncs + net->Ntanks;
167
- err = addnodeID(net, i, parser->Tok[0]);
168
- if (err) return setError(parser, 0, err);
169
-
170
- // Check for valid data
171
- if (n < 2) return 201;
172
- if (!getfloat(parser->Tok[1], &el)) return setError(parser, 1, 202);
173
-
174
- // Tank is reservoir
175
- if (n <= 3)
176
- {
177
- // Head pattern supplied
178
- if (n == 3)
179
- {
180
- pattern = findpattern(net, parser->Tok[2]);
181
- if (pattern < 0) return setError(parser, 2, 205);
182
- }
183
- }
184
- else if (n < 6) return 201;
185
-
186
- // Tank is a storage tank
187
- else
188
- {
189
- if (!getfloat(parser->Tok[2], &initlevel)) return setError(parser, 2, 202);
190
- if (!getfloat(parser->Tok[3], &minlevel)) return setError(parser, 3, 202);
191
- if (!getfloat(parser->Tok[4], &maxlevel)) return setError(parser, 4, 202);
192
- if (!getfloat(parser->Tok[5], &diam)) return setError(parser, 5, 202);
193
- if (n >= 7 && !getfloat(parser->Tok[6], &minvol)) return setError(parser, 6, 202);
194
-
195
- // If volume curve supplied check it exists
196
- if (n >= 8)
197
- {
198
- if (strlen(parser->Tok[7]) > 0 && *(parser->Tok[7]) != '*')
199
- {
200
- curve = findcurve(net, parser->Tok[7]);
201
- if (curve == 0) return setError(parser, 7, 206);
202
- net->Curve[curve].Type = VOLUME_CURVE;
203
- }
204
- }
205
-
206
- // Parse overflow indicator if present
207
- if (n >= 9)
208
- {
209
- if (match(parser->Tok[8], w_YES)) overflow = TRUE;
210
- else if (match(parser->Tok[8], w_NO)) overflow = FALSE;
211
- else return setError(parser, 8, 213);
212
- }
213
-
214
- if (initlevel < 0.0) return setError(parser, 2, 209);
215
- if (minlevel < 0.0) return setError(parser, 3, 209);
216
- if (maxlevel < 0.0) return setError(parser, 4, 209);
217
- if (diam < 0.0) return setError(parser, 5, 209);
218
- if (minvol < 0.0) return setError(parser, 6, 209);
219
- }
220
- node = &net->Node[i];
221
- tank = &net->Tank[net->Ntanks];
222
-
223
- node->X = MISSING;
224
- node->Y = MISSING;
225
- node->Rpt = 0;
226
- node->ResultIndex = 0;
227
- node->El = el;
228
- node->C0 = 0.0;
229
- node->S = NULL;
230
- node->Ke = 0.0;
231
- node->Type = (diam == 0) ? RESERVOIR : TANK;
232
- node->Comment = xstrcpy(&node->Comment, parser->Comment, MAXMSG);
233
- tank->Node = i;
234
- tank->H0 = initlevel;
235
- tank->Hmin = minlevel;
236
- tank->Hmax = maxlevel;
237
- tank->A = diam;
238
- tank->Pat = pattern;
239
- tank->Kb = MISSING;
240
- tank->CanOverflow = overflow;
241
-
242
- //*******************************************************************
243
- // NOTE: The min, max, & initial volumes set here are based on a
244
- // nominal tank diameter. They will be modified in INPUT1.C if
245
- // a volume curve is supplied for this tank.
246
- //*******************************************************************
247
- area = PI * SQR(diam) / 4.0;
248
- tank->Vmin = area * minlevel;
249
- if (minvol > 0.0) tank->Vmin = minvol;
250
- tank->V0 = tank->Vmin + area * (initlevel - minlevel);
251
- tank->Vmax = tank->Vmin + area * (maxlevel - minlevel);
252
-
253
- tank->Vcurve = curve;
254
- tank->MixModel = MIX1; // Completely mixed
255
- tank->V1max = 1.0; // Mixing compartment size fraction
256
- return 0;
257
- }
258
-
259
- int pipedata(Project *pr)
260
- /*
261
- **--------------------------------------------------------------
262
- ** Input: none
263
- ** Output: returns error code
264
- ** Purpose: processes pipe data
265
- ** Format:
266
- ** [PIPE]
267
- ** id node1 node2 length diam rcoeff (lcoeff) (status)
268
- **--------------------------------------------------------------
269
- */
270
- {
271
- Network *net = &pr->network;
272
- Parser *parser = &pr->parser;
273
-
274
- int j1, // Start-node index
275
- j2, // End-node index
276
- n; // # data items
277
- double length, // Pipe length
278
- diam, // Pipe diameter
279
- rcoeff, // Roughness coeff.
280
- lcoeff = 0.0; // Minor loss coeff
281
- LinkType type = PIPE; // Link type
282
- StatusType status = OPEN; // Link status
283
- Slink *link;
284
- int err = 0;
285
-
286
- // Add new pipe to data base
287
- n = parser->Ntokens;
288
- if (net->Nlinks == parser->MaxLinks) return 200;
289
- net->Npipes++;
290
- net->Nlinks++;
291
- err = addlinkID(net, net->Nlinks, parser->Tok[0]);
292
- if (err) return setError(parser, 0, err);
293
-
294
- // Check for valid data
295
- if (n < 6) return 201;
296
- if ((j1 = findnode(net, parser->Tok[1])) == 0) return setError(parser, 1, 203);
297
- if ((j2 = findnode(net, parser->Tok[2])) == 0) return setError(parser, 2, 203);
298
- if (j1 == j2) return setError(parser, 0, 222);
299
-
300
- if (!getfloat(parser->Tok[3], &length)) return setError(parser, 3, 202);
301
- if (length <= 0.0) return setError(parser, 3, 211);
302
- if (!getfloat(parser->Tok[4], &diam)) return setError(parser, 4, 202);
303
- if (diam <= 0.0) return setError(parser, 4, 211);
304
- if (!getfloat(parser->Tok[5], &rcoeff)) return setError(parser, 5, 202);
305
- if (rcoeff <= 0.0) setError(parser, 5, 211);
306
-
307
- // Either a loss coeff. or a status is supplied
308
- if (n == 7)
309
- {
310
- if (match(parser->Tok[6], w_CV)) type = CVPIPE;
311
- else if (match(parser->Tok[6], w_CLOSED)) status = CLOSED;
312
- else if (match(parser->Tok[6], w_OPEN)) status = OPEN;
313
- else if (!getfloat(parser->Tok[6], &lcoeff)) return setError(parser, 6, 202);
314
- }
315
-
316
- // Both a loss coeff. and a status is supplied
317
- if (n == 8)
318
- {
319
- if (!getfloat(parser->Tok[6], &lcoeff)) return setError(parser, 6, 202);
320
- if (match(parser->Tok[7], w_CV)) type = CVPIPE;
321
- else if (match(parser->Tok[7], w_CLOSED)) status = CLOSED;
322
- else if (match(parser->Tok[7], w_OPEN)) status = OPEN;
323
- else return setError(parser, 7, 213);
324
- }
325
- if (lcoeff < 0.0) return setError(parser, 6, 211);
326
-
327
- // Save pipe data
328
- link = &net->Link[net->Nlinks];
329
- link->N1 = j1;
330
- link->N2 = j2;
331
- link->Len = length;
332
- link->Diam = diam;
333
- link->Kc = rcoeff;
334
- link->Km = lcoeff;
335
- link->Kb = MISSING;
336
- link->Kw = MISSING;
337
- link->Type = type;
338
- link->Status = status;
339
- link->Rpt = 0;
340
- link->ResultIndex = 0;
341
- link->Comment = xstrcpy(&link->Comment, parser->Comment, MAXMSG);
342
- return 0;
343
- }
344
-
345
- int pumpdata(Project *pr)
346
- /*
347
- **--------------------------------------------------------------
348
- ** Input: none
349
- ** Output: returns error code
350
- ** Purpose: processes pump data
351
- ** Formats:
352
- ** [PUMP]
353
- ** (Version 1.x Format):
354
- ** id node1 node2 power
355
- ** id node1 node2 h1 q1
356
- ** id node1 node2 h0 h1 q1 h2 q2
357
- ** (Version 2 Format):
358
- ** id node1 node2 KEYWORD value {KEYWORD value ...}
359
- ** where KEYWORD = [POWER,HEAD,PATTERN,SPEED]
360
- **--------------------------------------------------------------
361
- */
362
- {
363
- Network *net = &pr->network;
364
- Parser *parser = &pr->parser;
365
-
366
- int j, m, // Token array indexes
367
- j1, // Start-node index
368
- j2, // End-node index
369
- n, // # data items
370
- c, p; // Curve & Pattern indexes
371
- double y;
372
- Slink *link;
373
- Spump *pump;
374
- int err = 0;
375
-
376
- /* Add new pump to data base */
377
- n = parser->Ntokens;
378
- if (net->Nlinks == parser->MaxLinks ||
379
- net->Npumps == parser->MaxPumps) return 200;
380
- net->Nlinks++;
381
- net->Npumps++;
382
- err = addlinkID(net, net->Nlinks, parser->Tok[0]);
383
- if (err) return setError(parser, 0, err);
384
-
385
- // Check for valid data
386
- if (n < 3) return 201;
387
- if ((j1 = findnode(net, parser->Tok[1])) == 0) return setError(parser, 1, 203);
388
- if ((j2 = findnode(net, parser->Tok[2])) == 0) return setError(parser, 2, 203);
389
- if (j1 == j2) return setError(parser, 0, 222);
390
-
391
- // Save pump data
392
- link = &net->Link[net->Nlinks];
393
- pump = &net->Pump[net->Npumps];
394
-
395
- link->N1 = j1;
396
- link->N2 = j2;
397
- link->Diam = 0;
398
- link->Len = 0.0;
399
- link->Kc = 1.0;
400
- link->Km = 0.0;
401
- link->Kb = 0.0;
402
- link->Kw = 0.0;
403
- link->Type = PUMP;
404
- link->Status = OPEN;
405
- link->Rpt = 0;
406
- link->ResultIndex = 0;
407
- link->Comment = xstrcpy(&link->Comment, parser->Comment, MAXMSG);
408
- pump->Link = net->Nlinks;
409
- pump->Ptype = NOCURVE; // NOCURVE is a placeholder
410
- pump->Hcurve = 0;
411
- pump->Ecurve = 0;
412
- pump->Upat = 0;
413
- pump->Ecost = 0.0;
414
- pump->Epat = 0;
415
- if (n < 4) return 0;
416
-
417
- // If 4-th token is a number then input follows Version 1.x format
418
- // so retrieve pump curve parameters
419
- if (getfloat(parser->Tok[3], &parser->X[0]))
420
- {
421
- m = 1;
422
- for (j = 4; j < n; j++)
423
- {
424
- if (!getfloat(parser->Tok[j], &parser->X[m])) return setError(parser, j, 202);
425
- m++;
426
- }
427
- return (getpumpcurve(pr, m));
428
- }
429
-
430
- // Otherwise input follows Version 2 format
431
- // so retrieve keyword/value pairs
432
- m = 4;
433
- while (m < n)
434
- {
435
- if (match(parser->Tok[m - 1], w_POWER)) // Const. HP curve
436
- {
437
- y = atof(parser->Tok[m]);
438
- if (y <= 0.0) return setError(parser, m, 202);
439
- pump->Ptype = CONST_HP;
440
- link->Km = y;
441
- }
442
- else if (match(parser->Tok[m - 1], w_HEAD)) // Custom pump curve
443
- {
444
- c = findcurve(net, parser->Tok[m]);
445
- if (c == 0) return setError(parser, m, 206);
446
- pump->Hcurve = c;
447
- }
448
- else if (match(parser->Tok[m - 1], w_PATTERN)) // Speed/status pattern
449
- {
450
- p = findpattern(net, parser->Tok[m]);
451
- if (p < 0) return setError(parser, m, 205);
452
- pump->Upat = p;
453
- }
454
- else if (match(parser->Tok[m - 1], w_SPEED)) // Speed setting
455
- {
456
- if (!getfloat(parser->Tok[m], &y)) return setError(parser, m, 202);
457
- if (y < 0.0) return setError(parser, m, 211);
458
- link->Kc = y;
459
- }
460
- else return 201;
461
- m = m + 2; // Move to next keyword token
462
- }
463
- return 0;
464
- }
465
-
466
- int valvedata(Project *pr)
467
- /*
468
- **--------------------------------------------------------------
469
- ** Input: none
470
- ** Output: returns error code
471
- ** Purpose: processes valve data
472
- ** Format:
473
- ** [VALVE]
474
- ** id node1 node2 diam type setting (lcoeff)
475
- **--------------------------------------------------------------
476
- */
477
- {
478
- Network *net = &pr->network;
479
- Parser *parser = &pr->parser;
480
-
481
- int c, // Curve index
482
- j1, // Start-node index
483
- j2, // End-node index
484
- n; // # data items
485
- char status = ACTIVE, // Valve status
486
- type; // Valve type
487
- double diam = 0.0, // Valve diameter
488
- setting, // Valve setting
489
- lcoeff = 0.0; // Minor loss coeff.
490
- Slink *link;
491
- int err = 0;
492
-
493
- // Add new valve to data base
494
- n = parser->Ntokens;
495
- if (net->Nlinks == parser->MaxLinks ||
496
- net->Nvalves == parser->MaxValves) return 200;
497
- net->Nvalves++;
498
- net->Nlinks++;
499
- err = addlinkID(net, net->Nlinks, parser->Tok[0]);
500
- if (err) return setError(parser, 0, err);
501
-
502
- // Check for valid data
503
- if (n < 6)
504
- return 201;
505
- if ((j1 = findnode(net, parser->Tok[1])) == 0)
506
- return setError(parser, 1, 203);
507
- if ((j2 = findnode(net, parser->Tok[2])) == 0)
508
- return setError(parser, 2, 203);
509
- if (j1 == j2)
510
- return setError(parser, 0, 222);
511
-
512
- if (match(parser->Tok[4], w_PRV))
513
- type = PRV;
514
- else if (match(parser->Tok[4], w_PSV))
515
- type = PSV;
516
- else if (match(parser->Tok[4], w_PBV))
517
- type = PBV;
518
- else if (match(parser->Tok[4], w_FCV))
519
- type = FCV;
520
- else if (match(parser->Tok[4], w_TCV))
521
- type = TCV;
522
- else if (match(parser->Tok[4], w_GPV))
523
- type = GPV;
524
- else
525
- return setError(parser, 4, 213);
526
-
527
- if (!getfloat(parser->Tok[3], &diam)) return setError(parser, 3, 202);
528
- if (diam <= 0.0) return setError(parser, 3, 211);
529
-
530
- // Find headloss curve for GPV
531
- if (type == GPV)
532
- {
533
- c = findcurve(net, parser->Tok[5]);
534
- if (c == 0) return setError(parser, 5, 206);
535
- setting = c;
536
- net->Curve[c].Type = HLOSS_CURVE;
537
- status = OPEN;
538
- }
539
- else if (!getfloat(parser->Tok[5], &setting)) return setError(parser, 5, 202);
540
- if (n >= 7 && !getfloat(parser->Tok[6], &lcoeff)) return setError(parser, 6, 202);
541
-
542
- // Check for illegal connections
543
- if (valvecheck(pr, net->Nlinks, type, j1, j2))
544
- {
545
- if (j1 > net->Njuncs) return setError(parser, 1, 219);
546
- else if (j2 > net->Njuncs) return setError(parser, 2, 219);
547
- else return setError(parser, -1, 220);
548
- }
549
-
550
- // Save valve data
551
- link = &net->Link[net->Nlinks];
552
- link->N1 = j1;
553
- link->N2 = j2;
554
- link->Diam = diam;
555
- link->Len = 0.0;
556
- link->Kc = setting;
557
- link->Km = lcoeff;
558
- link->Kb = 0.0;
559
- link->Kw = 0.0;
560
- link->Type = type;
561
- link->Status = status;
562
- link->Rpt = 0;
563
- link->ResultIndex = 0;
564
- link->Comment = xstrcpy(&link->Comment, parser->Comment, MAXMSG);
565
- net->Valve[net->Nvalves].Link = net->Nlinks;
566
- return 0;
567
- }
568
-
569
- int patterndata(Project *pr)
570
- /*
571
- **--------------------------------------------------------------
572
- ** Input: none
573
- ** Output: returns error code
574
- ** Purpose: processes time pattern data
575
- ** Format:
576
- ** [PATTERNS]
577
- ** id mult1 mult2 .....
578
- **--------------------------------------------------------------
579
- */
580
- {
581
- Network *net = &pr->network;
582
- Parser *parser = &pr->parser;
583
-
584
- int i, j, n, n1;
585
- double x;
586
- Spattern *pattern;
587
-
588
- // "n" is the number of pattern factors contained in the line
589
- n = parser->Ntokens - 1;
590
- if (n < 1) return 201;
591
-
592
- // Check if previous input line was for the same pattern
593
- if (parser->PrevPat && strcmp(parser->Tok[0], parser->PrevPat->ID) == 0)
594
- {
595
- pattern = parser->PrevPat;
596
- }
597
-
598
- // Otherwise retrieve pattern from the network's Pattern array
599
- else
600
- {
601
- i = findpattern(net, parser->Tok[0]);
602
- if (i <= 0) return setError(parser, 0, 205);
603
- pattern = &(net->Pattern[i]);
604
- if (pattern->Comment == NULL && parser->Comment[0])
605
- {
606
- pattern->Comment = xstrcpy(&pattern->Comment, parser->Comment, MAXMSG);
607
- }
608
- }
609
-
610
- // Expand size of the pattern's factors array
611
- n1 = pattern->Length;
612
- pattern->Length += n;
613
- pattern->F = realloc(pattern->F, pattern->Length * sizeof(double));
614
-
615
- // Add parsed multipliers to the pattern
616
- for (j = 1; j <= n; j++)
617
- {
618
- if (!getfloat(parser->Tok[j], &x)) return setError(parser, j, 202);
619
- pattern->F[n1 + j - 1] = x;
620
- }
621
-
622
- // Save a reference to this pattern for processing additional pattern data
623
- parser->PrevPat = pattern;
624
- return 0;
625
- }
626
-
627
- int curvedata(Project *pr)
628
- /*
629
- **------------------------------------------------------
630
- ** Input: none
631
- ** Output: returns error code
632
- ** Purpose: processes curve data
633
- ** Format:
634
- ** [CURVES]
635
- ** CurveID x-value y-value
636
- **------------------------------------------------------
637
- */
638
- {
639
- Network *net = &pr->network;
640
- Parser *parser = &pr->parser;
641
-
642
- int i;
643
- double x, y;
644
- Scurve *curve;
645
-
646
- // Check for valid data
647
- if (parser->Ntokens < 3) return 201;
648
- if (!getfloat(parser->Tok[1], &x)) return setError(parser, 1, 202);
649
- if (!getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
650
-
651
- // Check if previous input line was for the same curve
652
- if (parser->PrevCurve && strcmp(parser->Tok[0], parser->PrevCurve->ID) == 0)
653
- {
654
- curve = parser->PrevCurve;
655
- }
656
-
657
- // Otherwise retrieve curve from the network's Curve array
658
- else
659
- {
660
- i = findcurve(net, parser->Tok[0]);
661
- if (i == 0) return setError(parser, 0, 206);
662
- curve = &(net->Curve[i]);
663
- if (curve->Comment == NULL && parser->Comment[0])
664
- {
665
- curve->Comment = xstrcpy(&curve->Comment, parser->Comment, MAXMSG);
666
- }
667
- }
668
-
669
- // Expand size of data arrays if need be
670
- if (curve->Capacity == curve->Npts)
671
- {
672
- if (resizecurve(curve, curve->Capacity + 10) > 0) return 101;
673
- }
674
-
675
- // Add new data point to curve
676
- curve->X[curve->Npts] = x;
677
- curve->Y[curve->Npts] = y;
678
- curve->Npts++;
679
-
680
- // Save a reference to this curve for processing additional curve data
681
- parser->PrevCurve = curve;
682
- return 0;
683
- }
684
-
685
- int coordata(Project *pr)
686
- /*
687
- **--------------------------------------------------------------
688
- ** Input: none
689
- ** Output: returns error code
690
- ** Purpose: processes coordinate data
691
- ** Format:
692
- ** [COORD]
693
- ** id x y
694
- **--------------------------------------------------------------
695
- */
696
- {
697
- Network *net = &pr->network;
698
- Parser *parser = &pr->parser;
699
-
700
- int j;
701
- double x, y;
702
- Snode *node;
703
-
704
- // Check for valid node ID
705
- if (parser->Ntokens < 3) return 201;
706
- if ((j = findnode(net, parser->Tok[0])) == 0) return setError(parser, 0, 203);
707
-
708
- // Check for valid data
709
- if (!getfloat(parser->Tok[1], &x)) return setError(parser, 1, 202);
710
- if (!getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
711
-
712
- // Save coord data
713
- node = &net->Node[j];
714
- node->X = x;
715
- node->Y = y;
716
- return 0;
717
- }
718
-
719
- int vertexdata(Project *pr)
720
- /*
721
- **--------------------------------------------------------------
722
- ** Input: none
723
- ** Output: returns error code
724
- ** Purpose: processes link vertex data
725
- ** Format:
726
- ** [VERTICES]
727
- ** id x y
728
- **--------------------------------------------------------------
729
- */
730
- {
731
- Network *net = &pr->network;
732
- Parser *parser = &pr->parser;
733
-
734
- int j;
735
- double x, y;
736
-
737
- // Check for valid link ID
738
- if (parser->Ntokens < 3) return 201;
739
- if ((j = findlink(net, parser->Tok[0])) == 0) return setError(parser, 0, 204);
740
-
741
- // Check for valid coordinate data
742
- if (!getfloat(parser->Tok[1], &x)) return setError(parser, 1, 202);
743
- if (!getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
744
-
745
- // Add to link's list of vertex points
746
- return addlinkvertex(&net->Link[j], x, y);
747
- }
748
-
749
-
750
- int demanddata(Project *pr)
751
- /*
752
- **--------------------------------------------------------------
753
- ** Input: none
754
- ** Output: returns error code
755
- ** Purpose: processes node demand data
756
- ** Format:
757
- ** [DEMANDS]
758
- ** MULTIPLY factor
759
- ** node base_demand (pattern)
760
- **
761
- ** NOTE: Demands entered in this section replace those
762
- ** entered in the [JUNCTIONS] section
763
- **--------------------------------------------------------------
764
- */
765
- {
766
- Network *net = &pr->network;
767
- Hydraul *hyd = &pr->hydraul;
768
- Parser *parser = &pr->parser;
769
-
770
- int j, n, p = 0;
771
- double y;
772
-
773
- Pdemand demand;
774
-
775
- // Extract data from tokens
776
- n = parser->Ntokens;
777
- if (n < 2) return 201;
778
- if (!getfloat(parser->Tok[1], &y)) return setError(parser, 1, 202);
779
-
780
- // If MULTIPLY command, save multiplier
781
- if (match(parser->Tok[0], w_MULTIPLY))
782
- {
783
- if (y <= 0.0) return setError(parser, 1, 213);
784
- else hyd->Dmult = y;
785
- return 0;
786
- }
787
-
788
- // Otherwise find node (and pattern) being referenced
789
- if ((j = findnode(net, parser->Tok[0])) == 0) return setError(parser, 0, 203);
790
- if (j > net->Njuncs) return 0;
791
- if (n >= 3)
792
- {
793
- p = findpattern(net, parser->Tok[2]);
794
- if (p < 0) return setError(parser, 2, 205);
795
- }
796
-
797
- // Replace any demand entered in [JUNCTIONS] section
798
- demand = net->Node[j].D;
799
- if (demand && hyd->NodeDemand[j] != MISSING)
800
- {
801
- // First category encountered will overwrite demand category
802
- // created when junction was read from [JUNCTIONS] section
803
- demand->Base = y;
804
- demand->Pat = p;
805
- if (parser->Comment[0])
806
- {
807
- demand->Name = xstrcpy(&demand->Name, parser->Comment, MAXID);
808
- }
809
- hyd->NodeDemand[j] = MISSING; // marker - next iteration will append a new category.
810
- }
811
-
812
- // Otherwise add new demand to junction
813
- else if (!adddemand(&net->Node[j], y, p, parser->Comment) > 0) return 101;
814
- return 0;
815
- }
816
-
817
- int controldata(Project *pr)
818
- /*
819
- **--------------------------------------------------------------
820
- ** Input: none
821
- ** Output: returns error code
822
- ** Purpose: processes simple controls
823
- ** Formats:
824
- ** [CONTROLS]
825
- ** LINK linkID setting IF NODE nodeID {BELOW/ABOVE} level
826
- ** LINK linkID setting AT TIME value (units)
827
- ** LINK linkID setting AT CLOCKTIME value (units)
828
- ** (0) (1) (2) (3) (4) (5) (6) (7)
829
- **--------------------------------------------------------------
830
- */
831
- {
832
- Network *net = &pr->network;
833
- Parser *parser = &pr->parser;
834
-
835
- int i = 0, // Node index
836
- k, // Link index
837
- n; // # data items
838
- double setting = MISSING, // Link setting
839
- time = 0.0, // Simulation time
840
- level = 0.0; // Pressure or tank level
841
- StatusType status = ACTIVE; // Link status
842
- ControlType ctltype; // Control type
843
- LinkType linktype; // Link type
844
- Scontrol *control;
845
-
846
- // Check for sufficient number of input tokens
847
- n = parser->Ntokens;
848
- if (n < 6) return 201;
849
-
850
- // Check that controlled link exists
851
- k = findlink(net, parser->Tok[1]);
852
- if (k == 0) return setError(parser, 1, 204);
853
-
854
- // Cannot control a check valve
855
- linktype = net->Link[k].Type;
856
- if (linktype == CVPIPE) return setError(parser, 1, 207);
857
-
858
- // Parse control setting into a status level or numerical setting
859
- if (match(parser->Tok[2], w_OPEN))
860
- {
861
- status = OPEN;
862
- if (linktype == PUMP) setting = 1.0;
863
- if (linktype == GPV) setting = net->Link[k].Kc;
864
- }
865
- else if (match(parser->Tok[2], w_CLOSED))
866
- {
867
- status = CLOSED;
868
- if (linktype == PUMP) setting = 0.0;
869
- if (linktype == GPV) setting = net->Link[k].Kc;
870
- }
871
- else if (linktype == GPV) return setError(parser, 1, 207);
872
- else if (!getfloat(parser->Tok[2], &setting)) return setError(parser, 2, 202);
873
-
874
- // Set status for pump in case speed setting was supplied
875
- // or for pipe if numerical setting was supplied
876
- if (linktype == PUMP || linktype == PIPE)
877
- {
878
- if (setting != MISSING)
879
- {
880
- if (setting < 0.0) return setError(parser, 2, 211);
881
- else if (setting == 0.0) status = CLOSED;
882
- else status = OPEN;
883
- }
884
- }
885
-
886
- // Determine type of control
887
- if (match(parser->Tok[4], w_TIME)) ctltype = TIMER;
888
- else if (match(parser->Tok[4], w_CLOCKTIME)) ctltype = TIMEOFDAY;
889
- else
890
- {
891
- if (n < 8) return 201;
892
- if ((i = findnode(net, parser->Tok[5])) == 0) return setError(parser, 5, 203);
893
- if (match(parser->Tok[6], w_BELOW)) ctltype = LOWLEVEL;
894
- else if (match(parser->Tok[6], w_ABOVE)) ctltype = HILEVEL;
895
- else return setError(parser, 6, 213);
896
- }
897
-
898
- // Parse control level or time
899
- switch (ctltype)
900
- {
901
- case TIMER:
902
- case TIMEOFDAY:
903
- if (n == 6) time = hour(parser->Tok[5], "");
904
- if (n == 7) time = hour(parser->Tok[5], parser->Tok[6]);
905
- if (time < 0.0) return setError(parser, 5, 213);
906
- break;
907
- case LOWLEVEL:
908
- case HILEVEL:
909
- if (!getfloat(parser->Tok[7], &level)) return setError(parser, 7, 202);
910
- break;
911
- }
912
-
913
- // Fill in fields of control data structure
914
- net->Ncontrols++;
915
- if (net->Ncontrols > parser->MaxControls) return 200;
916
- control = &net->Control[net->Ncontrols];
917
- control->Link = k;
918
- control->Node = i;
919
- control->Type = ctltype;
920
- control->Status = status;
921
- control->Setting = setting;
922
- control->Time = (long)(3600.0 * time);
923
- if (ctltype == TIMEOFDAY) control->Time %= SECperDAY;
924
- control->Grade = level;
925
- return 0;
926
- }
927
-
928
- int sourcedata(Project *pr)
929
- /*
930
- **--------------------------------------------------------------
931
- ** Input: none
932
- ** Output: returns error code
933
- ** Purpose: processes water quality source data
934
- ** Formats:
935
- ** [SOURCE]
936
- ** node sourcetype quality (pattern)
937
- **
938
- ** NOTE: units of mass-based source are mass/min
939
- **--------------------------------------------------------------
940
- */
941
- {
942
- Network *net = &pr->network;
943
- Parser *parser = &pr->parser;
944
-
945
- int i, // Token with quality value
946
- j, // Node index
947
- n, // # data items
948
- p = 0; // Time pattern index
949
- char type = CONCEN; // Source type
950
- double c0 = 0; // Initial quality
951
- Psource source;
952
-
953
- // Check for enough tokens & that source node exists
954
- n = parser->Ntokens;
955
- if (n < 2) return 201;
956
- if ((j = findnode(net, parser->Tok[0])) == 0) return setError(parser, 0, 203);
957
-
958
- // Parse source type
959
- // NOTE: Under old 1.1 format, SourceType not supplied so
960
- // let i = index of token that contains quality value
961
- i = 2;
962
- if (match(parser->Tok[1], w_CONCEN)) type = CONCEN;
963
- else if (match(parser->Tok[1], w_MASS)) type = MASS;
964
- else if (match(parser->Tok[1], w_SETPOINT)) type = SETPOINT;
965
- else if (match(parser->Tok[1], w_FLOWPACED)) type = FLOWPACED;
966
- else i = 1;
967
-
968
- // Parse source quality
969
- if (!getfloat(parser->Tok[i], &c0))
970
- {
971
- if (i == 1) return setError(parser, i, 213);
972
- else return setError(parser, i, 202);
973
- }
974
-
975
- // Parse optional source time pattern
976
- if (n > i + 1 && strlen(parser->Tok[i + 1]) > 0 &&
977
- strcmp(parser->Tok[i + 1], "*") != 0)
978
- {
979
- p = findpattern(net, parser->Tok[i + 1]);
980
- if (p < 0) return setError(parser, i + 1, 205);
981
- }
982
-
983
- // Destroy any existing source assigned to node
984
- if (net->Node[j].S != NULL) free(net->Node[j].S);
985
-
986
- // Create a new source & assign it to the node
987
- source = (struct Ssource *)malloc(sizeof(struct Ssource));
988
- if (source == NULL) return 101;
989
- source->C0 = c0;
990
- source->Pat = p;
991
- source->Type = type;
992
- net->Node[j].S = source;
993
- return 0;
994
- }
995
-
996
- int emitterdata(Project *pr)
997
- /*
998
- **--------------------------------------------------------------
999
- ** Input: none
1000
- ** Output: returns error code
1001
- ** Purpose: processes junction emitter data
1002
- ** Format:
1003
- ** [EMITTER]
1004
- ** node Ke
1005
- **--------------------------------------------------------------
1006
- */
1007
- {
1008
- Network *net = &pr->network;
1009
- Parser *parser = &pr->parser;
1010
-
1011
- int j, // Node index
1012
- n; // # data items
1013
- double k; // Flow coeff.
1014
-
1015
- // Check that node exists & is a junction
1016
- n = parser->Ntokens;
1017
- if (n < 2) return 201;
1018
- if ((j = findnode(net, parser->Tok[0])) == 0) return setError(parser, 0, 203);
1019
- if (j > net->Njuncs) return 0;
1020
-
1021
- // Parse emitter flow coeff.
1022
- if (!getfloat(parser->Tok[1], &k)) return setError(parser, 1, 202);
1023
- if (k < 0.0) return setError(parser, 1, 209);
1024
- net->Node[j].Ke = k;
1025
- return 0;
1026
- }
1027
-
1028
- int qualdata(Project *pr)
1029
- /*
1030
- **--------------------------------------------------------------
1031
- ** Input: none
1032
- ** Output: returns error code
1033
- ** Purpose: processes initial water quality data
1034
- ** Formats:
1035
- ** [QUALITY]
1036
- ** node initqual
1037
- ** node1 node2 initqual
1038
- **--------------------------------------------------------------
1039
- */
1040
- {
1041
- Network *net = &pr->network;
1042
- Parser *parser = &pr->parser;
1043
-
1044
- int j, n;
1045
- long i, i1, i2;
1046
- double c0;
1047
- Snode *Node = net->Node;
1048
-
1049
- if (net->Nnodes == 0) return setError(parser, 0, 203); // No nodes defined yet
1050
- n = parser->Ntokens;
1051
- if (n < 2) return 0;
1052
-
1053
- // Single node name supplied
1054
- if (n == 2)
1055
- {
1056
- if ((j = findnode(net,parser->Tok[0])) == 0) return setError(parser, 0, 203);
1057
- if (!getfloat(parser->Tok[1], &c0)) return setError(parser, 1, 202);
1058
- if (c0 < 0.0) return setError(parser, 1, 209);
1059
- Node[j].C0 = c0;
1060
- }
1061
-
1062
- // Range of node names supplied
1063
- else
1064
- {
1065
- // Parse quality value
1066
- if (!getfloat(parser->Tok[2], &c0)) return setError(parser, 2, 202);
1067
- if (c0 < 0.0) return setError(parser, 2, 209);
1068
-
1069
- // If numerical node names supplied, then use numerical comparison
1070
- // to find which nodes are assigned the quality value
1071
- if ((i1 = atol(parser->Tok[0])) > 0 &&
1072
- (i2 = atol(parser->Tok[1])) > 0)
1073
- {
1074
- for (j = 1; j <= net->Nnodes; j++)
1075
- {
1076
- i = atol(Node[j].ID);
1077
- if (i >= i1 && i <= i2) Node[j].C0 = c0;
1078
- }
1079
- }
1080
-
1081
- // Otherwise use lexicographic comparison
1082
- else
1083
- {
1084
- for (j = 1; j <= net->Nnodes; j++)
1085
- {
1086
- if ((strcmp(parser->Tok[0], Node[j].ID) <= 0) &&
1087
- (strcmp(parser->Tok[1], Node[j].ID) >= 0)
1088
- ) Node[j].C0 = c0;
1089
- }
1090
- }
1091
- }
1092
- return 0;
1093
- }
1094
-
1095
- int reactdata(Project *pr)
1096
- /*
1097
- **--------------------------------------------------------------
1098
- ** Input: none
1099
- ** Output: returns error code
1100
- ** Purpose: processes reaction coeff. data
1101
- ** Formats:
1102
- ** [REACTIONS]
1103
- ** ORDER {BULK/WALL/TANK} value
1104
- ** GLOBAL BULK coeff
1105
- ** GLOBAL WALL coeff
1106
- ** BULK link1 (link2) coeff
1107
- ** WALL link1 (link2) coeff
1108
- ** TANK node1 (node2) coeff
1109
- ** LIMITING POTENTIAL value
1110
- ** ROUGHNESS CORRELATION value
1111
- **--------------------------------------------------------------
1112
- */
1113
- {
1114
- Network *net = &pr->network;
1115
- Quality *qual = &pr->quality;
1116
- Parser *parser = &pr->parser;
1117
-
1118
- int item, j, n;
1119
- long i, i1, i2;
1120
- double y;
1121
-
1122
- // Skip line if insufficient data
1123
- n = parser->Ntokens;
1124
- if (n < 3) return 0;
1125
-
1126
- // Keyword is ORDER
1127
- if (match(parser->Tok[0], w_ORDER))
1128
- {
1129
- if (!getfloat(parser->Tok[n - 1], &y)) return setError(parser, n-1, 202);
1130
- if (match(parser->Tok[1], w_BULK)) qual->BulkOrder = y;
1131
- else if (match(parser->Tok[1], w_TANK)) qual->TankOrder = y;
1132
- else if (match(parser->Tok[1], w_WALL))
1133
- {
1134
- if (y == 0.0) qual->WallOrder = 0.0;
1135
- else if (y == 1.0) qual->WallOrder = 1.0;
1136
- else return setError(parser, n-1, 213);
1137
- }
1138
- else return setError(parser, 1, 213);
1139
- return 0;
1140
- }
1141
-
1142
- // Keyword is ROUGHNESS
1143
- if (match(parser->Tok[0], w_ROUGHNESS))
1144
- {
1145
- if (!getfloat(parser->Tok[n - 1], &y)) return setError(parser, n-1, 202);
1146
- qual->Rfactor = y;
1147
- return 0;
1148
- }
1149
-
1150
- // Keyword is LIMITING
1151
- if (match(parser->Tok[0], w_LIMITING))
1152
- {
1153
- if (!getfloat(parser->Tok[n - 1], &y)) return setError(parser, n-1, 202);
1154
- qual->Climit = y;
1155
- return 0;
1156
- }
1157
-
1158
- // Keyword is GLOBAL
1159
- if (match(parser->Tok[0], w_GLOBAL))
1160
- {
1161
- if (!getfloat(parser->Tok[n - 1], &y)) return setError(parser, n-1, 202);
1162
- if (match(parser->Tok[1], w_BULK)) qual->Kbulk = y;
1163
- else if (match(parser->Tok[1], w_WALL)) qual->Kwall = y;
1164
- else return setError(parser, 1, 213);
1165
- return 0;
1166
- }
1167
-
1168
- // Keyword is BULK, WALL or TANK
1169
- if (match(parser->Tok[0], w_BULK)) item = 1;
1170
- else if (match(parser->Tok[0], w_WALL)) item = 2;
1171
- else if (match(parser->Tok[0], w_TANK)) item = 3;
1172
- else return setError(parser, 0, 213);
1173
-
1174
- // Case where tank rate coeffs. are being set
1175
- if (item == 3)
1176
- {
1177
- // Get the rate coeff. value
1178
- if (!getfloat(parser->Tok[n - 1], &y)) return setError(parser, n-1, 202);
1179
-
1180
- // Case where just a single tank is specified
1181
- if (n == 3)
1182
- {
1183
- if ((j = findnode(net,parser->Tok[1])) <= net->Njuncs) return 0;
1184
- net->Tank[j - net->Njuncs].Kb = y;
1185
- }
1186
-
1187
- // Case where a numerical range of tank IDs is specified
1188
- else if ((i1 = atol(parser->Tok[1])) > 0 &&
1189
- (i2 = atol(parser->Tok[2])) > 0)
1190
- {
1191
- for (j = net->Njuncs + 1; j <= net->Nnodes; j++)
1192
- {
1193
- i = atol(net->Node[j].ID);
1194
- if (i >= i1 && i <= i2) net->Tank[j - net->Njuncs].Kb = y;
1195
- }
1196
- }
1197
-
1198
- // Case where a general range of tank IDs is specified
1199
- else for (j = net->Njuncs + 1; j <= net->Nnodes; j++)
1200
- {
1201
- if ((strcmp(parser->Tok[1], net->Node[j].ID) <= 0) &&
1202
- (strcmp(parser->Tok[2], net->Node[j].ID) >= 0)
1203
- ) net->Tank[j - net->Njuncs].Kb = y;
1204
- }
1205
- }
1206
-
1207
- // Case where pipe rate coeffs. are being set
1208
- else
1209
- {
1210
- // Get the rate coeff. value
1211
- if (!getfloat(parser->Tok[n - 1], &y)) return setError(parser, n-1, 202);
1212
- if (net->Nlinks == 0) return 0;
1213
-
1214
- // Case where just a single link is specified
1215
- if (n == 3)
1216
- {
1217
- if ((j = findlink(net, parser->Tok[1])) == 0) return 0;
1218
- if (item == 1) net->Link[j].Kb = y;
1219
- else net->Link[j].Kw = y;
1220
- }
1221
-
1222
- // Case where a numerical range of link IDs is specified
1223
- else if ((i1 = atol(parser->Tok[1])) > 0 &&
1224
- (i2 = atol(parser->Tok[2])) > 0)
1225
- {
1226
- for (j = 1; j <= net->Nlinks; j++)
1227
- {
1228
- i = atol(net->Link[j].ID);
1229
- if (i >= i1 && i <= i2)
1230
- {
1231
- if (item == 1) net->Link[j].Kb = y;
1232
- else net->Link[j].Kw = y;
1233
- }
1234
- }
1235
- }
1236
-
1237
- // Case where a general range of link IDs is specified
1238
- else for (j = 1; j <= net->Nlinks; j++)
1239
- {
1240
- if ((strcmp(parser->Tok[1], net->Link[j].ID) <= 0) &&
1241
- (strcmp(parser->Tok[2], net->Link[j].ID) >= 0))
1242
- {
1243
- if (item == 1) net->Link[j].Kb = y;
1244
- else net->Link[j].Kw = y;
1245
- }
1246
- }
1247
- }
1248
- return 0;
1249
- }
1250
-
1251
- int mixingdata(Project *pr)
1252
- /*
1253
- **-------------------------------------------------------------
1254
- ** Input: none
1255
- ** Output: returns error code
1256
- ** Purpose: processes tank mixing data
1257
- ** Format:
1258
- ** [MIXING]
1259
- ** TankID MixModel FractVolume
1260
- **-------------------------------------------------------------
1261
- */
1262
- {
1263
- Network *net = &pr->network;
1264
- Parser *parser = &pr->parser;
1265
-
1266
- int i, // Tank index
1267
- j, // Node index
1268
- m, // Type of mixing model
1269
- n; // Number of data items
1270
- double v; // Mixing zone volume fraction
1271
-
1272
- // Check for valid data
1273
- if (net->Nnodes == 0) return setError(parser, 0, 203);
1274
- n = parser->Ntokens;
1275
- if (n < 2) return 0;
1276
- j = findnode(net, parser->Tok[0]);
1277
- if (j == 0) return setError(parser, 0, 203);
1278
- if (j <= net->Njuncs) return 0;
1279
- if ((m = findmatch(parser->Tok[1], MixTxt)) < 0) return setError(parser, 1, 213);
1280
-
1281
- // Find mixing zone volume fraction (which can't be 0)
1282
- v = 1.0;
1283
- if ((m == MIX2) && (n == 3) &&
1284
- (!getfloat(parser->Tok[2], &v))) return setError(parser, 2, 202);
1285
- if (v == 0.0) v = 1.0;
1286
-
1287
- // Assign mixing data to tank (return if tank is a reservoir)
1288
- i = j - net->Njuncs;
1289
- if (net->Tank[i].A == 0.0) return 0;
1290
- net->Tank[i].MixModel = (char)m;
1291
- net->Tank[i].V1max = v;
1292
- return 0;
1293
- }
1294
-
1295
- int statusdata(Project *pr)
1296
- /*
1297
- **--------------------------------------------------------------
1298
- ** Input: none
1299
- ** Output: returns error code
1300
- ** Purpose: processes link initial status data
1301
- ** Formats:
1302
- ** [STATUS]
1303
- ** link value
1304
- ** link1 (link2) value
1305
- **--------------------------------------------------------------
1306
- */
1307
- {
1308
- Network *net = &pr->network;
1309
- Parser *parser = &pr->parser;
1310
-
1311
- int j, n;
1312
- long i, i1, i2;
1313
- double y = 0.0;
1314
- char status = ACTIVE;
1315
-
1316
- if (net->Nlinks == 0) return setError(parser, 0, 204);
1317
- n = parser->Ntokens - 1;
1318
- if (n < 1) return 201;
1319
-
1320
- // Check for legal status setting
1321
- if (match(parser->Tok[n], w_OPEN)) status = OPEN;
1322
- else if (match(parser->Tok[n], w_CLOSED)) status = CLOSED;
1323
- else
1324
- {
1325
- if (!getfloat(parser->Tok[n], &y)) return setError(parser, n, 202);
1326
- if (y < 0.0) return setError(parser, n, 211);
1327
- }
1328
-
1329
- // A single link ID was supplied
1330
- if (n == 1)
1331
- {
1332
- if ((j = findlink(net, parser->Tok[0])) == 0) return setError(parser, 0, 204);
1333
-
1334
- // Cannot change status of a Check Valve
1335
- if (net->Link[j].Type == CVPIPE) return setError(parser, 0, 207);
1336
-
1337
- // Cannot change setting for a GPV
1338
- if (net->Link[j].Type == GPV && status == ACTIVE) return setError(parser, 0, 207);
1339
- changestatus(net, j, status, y);
1340
- }
1341
-
1342
- // A range of numerical link ID's was supplied
1343
- else if ((i1 = atol(parser->Tok[0])) > 0 &&
1344
- (i2 = atol(parser->Tok[1])) > 0)
1345
- {
1346
- for (j = 1; j <= net->Nlinks; j++)
1347
- {
1348
- i = atol(net->Link[j].ID);
1349
- if (i >= i1 && i <= i2) changestatus(net, j, status, y);
1350
- }
1351
- }
1352
-
1353
- // A range of general link ID's was supplied
1354
- else for (j = 1; j <= net->Nlinks; j++)
1355
- {
1356
- if ((strcmp(parser->Tok[0], net->Link[j].ID) <= 0) &&
1357
- (strcmp(parser->Tok[1], net->Link[j].ID) >= 0)
1358
- ) changestatus(net, j, status, y);
1359
- }
1360
- return 0;
1361
- }
1362
-
1363
- int energydata(Project *pr)
1364
- /*
1365
- **--------------------------------------------------------------
1366
- ** Input: none
1367
- ** Output: returns error code
1368
- ** Purpose: processes pump energy data
1369
- ** Formats:
1370
- ** [ENERGY]
1371
- ** GLOBAL {PRICE/PATTERN/EFFIC} value
1372
- ** PUMP id {PRICE/PATTERN/EFFIC} value
1373
- ** DEMAND CHARGE value
1374
- **--------------------------------------------------------------
1375
- */
1376
- {
1377
- Network *net = &pr->network;
1378
- Hydraul *hyd = &pr->hydraul;
1379
- Parser *parser = &pr->parser;
1380
-
1381
- int j, k, n, p, c;
1382
- double y;
1383
-
1384
- Slink *Link = net->Link;
1385
- Spump *Pump = net->Pump;
1386
-
1387
- // Check for sufficient data
1388
- n = parser->Ntokens;
1389
- if (n < 3) return 201;
1390
-
1391
- // First keyword is DEMAND
1392
- if (match(parser->Tok[0], w_DMNDCHARGE))
1393
- {
1394
- if (!getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
1395
- if (y < 0.0) return setError(parser, 2, 213);
1396
- hyd->Dcost = y;
1397
- return 0;
1398
- }
1399
-
1400
- // First keyword is GLOBAL (remaining data refer to global options)
1401
- if (match(parser->Tok[0], w_GLOBAL))
1402
- {
1403
- j = 0;
1404
- }
1405
-
1406
- // First keyword is PUMP (remaining data refer to a specific pump)
1407
- else if (match(parser->Tok[0], w_PUMP))
1408
- {
1409
- if (n < 4) return 201;
1410
- k = findlink(net,parser->Tok[1]);
1411
- if (k == 0) return setError(parser, 1, 216);
1412
- if (Link[k].Type != PUMP) return setError(parser, 1, 216);
1413
- j = findpump(net, k);
1414
- }
1415
- else return setError(parser, 0, 213);
1416
-
1417
- // PRICE parameter being set
1418
- if (match(parser->Tok[n - 2], w_PRICE))
1419
- {
1420
- if (!getfloat(parser->Tok[n - 1], &y)) return setError(parser, n-1, 202);
1421
- if (y < 0.0) return setError(parser, n-1, 217);
1422
- if (j == 0) hyd->Ecost = y;
1423
- else Pump[j].Ecost = y;
1424
- return 0;
1425
- }
1426
-
1427
- // Price PATTERN being set
1428
- else if (match(parser->Tok[n - 2], w_PATTERN))
1429
- {
1430
- p = findpattern(net, parser->Tok[n - 1]);
1431
- if (p < 0) return setError(parser, n - 1, 205);
1432
- if (j == 0) hyd->Epat = p;
1433
- else Pump[j].Epat = p;
1434
- return 0;
1435
- }
1436
-
1437
- // Pump EFFIC being set
1438
- else if (match(parser->Tok[n - 2], w_EFFIC))
1439
- {
1440
- if (j == 0)
1441
- {
1442
- if (!getfloat(parser->Tok[n - 1], &y)) return setError(parser, n - 1, 202);
1443
- if (y <= 0.0) return setError(parser, n - 1, 217);
1444
- hyd->Epump = y;
1445
- }
1446
- else
1447
- {
1448
- c = findcurve(net, parser->Tok[n - 1]);
1449
- if (c == 0) return setError(parser, n - 1, 206);
1450
- Pump[j].Ecurve = c;
1451
- net->Curve[c].Type = EFFIC_CURVE;
1452
- }
1453
- return 0;
1454
- }
1455
- return 201;
1456
- }
1457
-
1458
- int reportdata(Project *pr)
1459
- /*
1460
- **--------------------------------------------------------------
1461
- ** Input: none
1462
- ** Output: returns error code
1463
- ** Purpose: processes report options data
1464
- ** Formats:
1465
- ** PAGE linesperpage
1466
- ** STATUS {NONE/YES/FULL}
1467
- ** SUMMARY {YES/NO}
1468
- ** MESSAGES {YES/NO}
1469
- ** ENERGY {NO/YES}
1470
- ** NODES {NONE/ALL}
1471
- ** NODES node1 node2 ...
1472
- ** LINKS {NONE/ALL}
1473
- ** LINKS link1 link2 ...
1474
- ** FILE filename
1475
- ** variable {YES/NO}
1476
- ** variable {BELOW/ABOVE/PRECISION} value
1477
- **--------------------------------------------------------------
1478
- */
1479
- {
1480
- Network *net = &pr->network;
1481
- Report *rpt = &pr->report;
1482
- Parser *parser = &pr->parser;
1483
-
1484
- int i, j, n;
1485
- double y;
1486
-
1487
- n = parser->Ntokens - 1;
1488
- if (n < 1) return 201;
1489
-
1490
- // Value for page size
1491
- if (match(parser->Tok[0], w_PAGE))
1492
- {
1493
- if (!getfloat(parser->Tok[n], &y)) return setError(parser, n, 202);
1494
- if (y < 0.0 || y > 255.0) return setError(parser, n, 213);
1495
- rpt->PageSize = (int)y;
1496
- return 0;
1497
- }
1498
-
1499
- // Request that status reports be written
1500
- if (match(parser->Tok[0], w_STATUS))
1501
- {
1502
- if (match(parser->Tok[n], w_NO)) rpt->Statflag = FALSE;
1503
- if (match(parser->Tok[n], w_YES)) rpt->Statflag = TRUE;
1504
- if (match(parser->Tok[n], w_FULL)) rpt->Statflag = FULL;
1505
- return 0;
1506
- }
1507
-
1508
- // Request summary report
1509
- if (match(parser->Tok[0], w_SUMMARY))
1510
- {
1511
- if (match(parser->Tok[n], w_NO)) rpt->Summaryflag = FALSE;
1512
- if (match(parser->Tok[n], w_YES)) rpt->Summaryflag = TRUE;
1513
- return 0;
1514
- }
1515
-
1516
- // Request error/warning message reporting
1517
- if (match(parser->Tok[0], w_MESSAGES))
1518
- {
1519
- if (match(parser->Tok[n], w_NO)) rpt->Messageflag = FALSE;
1520
- if (match(parser->Tok[n], w_YES)) rpt->Messageflag = TRUE;
1521
- return 0;
1522
- }
1523
-
1524
- // Request an energy usage report
1525
- if (match(parser->Tok[0], w_ENERGY))
1526
- {
1527
- if (match(parser->Tok[n], w_NO)) rpt->Energyflag = FALSE;
1528
- if (match(parser->Tok[n], w_YES)) rpt->Energyflag = TRUE;
1529
- return 0;
1530
- }
1531
-
1532
- // Particular reporting nodes specified
1533
- if (match(parser->Tok[0], w_NODE))
1534
- {
1535
- if (match(parser->Tok[n], w_NONE)) rpt->Nodeflag = 0; // No nodes
1536
- else if (match(parser->Tok[n], w_ALL)) rpt->Nodeflag = 1; // All nodes
1537
- else
1538
- {
1539
- if (net->Nnodes == 0) return setError(parser, 1, 203);
1540
- for (i = 1; i <= n; i++)
1541
- {
1542
- if ((j = findnode(net, parser->Tok[i])) == 0) return setError(parser, i, 203);
1543
- net->Node[j].Rpt = 1;
1544
- }
1545
- rpt->Nodeflag = 2;
1546
- }
1547
- return 0;
1548
- }
1549
-
1550
- // Particular reporting links specified
1551
- if (match(parser->Tok[0], w_LINK))
1552
- {
1553
- if (match(parser->Tok[n], w_NONE)) rpt->Linkflag = 0;
1554
- else if (match(parser->Tok[n], w_ALL)) rpt->Linkflag = 1;
1555
- else
1556
- {
1557
- if (net->Nlinks == 0) return setError(parser, 1, 204);
1558
- for (i = 1; i <= n; i++)
1559
- {
1560
- if ((j = findlink(net, parser->Tok[i])) == 0) return setError(parser, i, 204);
1561
- net->Link[j].Rpt = 1;
1562
- }
1563
- rpt->Linkflag = 2;
1564
- }
1565
- return 0;
1566
- }
1567
-
1568
- // Report fields specified
1569
- // Special case needed to distinguish "HEAD" from "HEADLOSS"
1570
- if (strcomp(parser->Tok[0], t_HEADLOSS)) i = HEADLOSS;
1571
- else i = findmatch(parser->Tok[0], Fldname);
1572
- if (i >= 0)
1573
- {
1574
- if (i > FRICTION) return setError(parser, 0, 213);
1575
- if (parser->Ntokens == 1 || match(parser->Tok[1], w_YES))
1576
- {
1577
- rpt->Field[i].Enabled = TRUE;
1578
- return 0;
1579
- }
1580
-
1581
- if (match(parser->Tok[1], w_NO))
1582
- {
1583
- rpt->Field[i].Enabled = FALSE;
1584
- return 0;
1585
- }
1586
-
1587
- // Get field qualifier type
1588
- if (parser->Ntokens < 3) return 201;
1589
- if (match(parser->Tok[1], w_BELOW)) j = LOW;
1590
- else if (match(parser->Tok[1], w_ABOVE)) j = HI;
1591
- else if (match(parser->Tok[1], w_PRECISION)) j = PREC;
1592
- else return setError(parser, 1, 213);
1593
-
1594
- // Get field qualifier value
1595
- if (!getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
1596
- if (j == PREC)
1597
- {
1598
- rpt->Field[i].Enabled = TRUE;
1599
- rpt->Field[i].Precision = ROUND(y);
1600
- }
1601
- else rpt->Field[i].RptLim[j] = y;
1602
- return (0);
1603
- }
1604
-
1605
- // Name of external report file
1606
- if (match(parser->Tok[0], w_FILE))
1607
- {
1608
- strncpy(rpt->Rpt2Fname, parser->Tok[1], MAXFNAME);
1609
- return 0;
1610
- }
1611
-
1612
- // If get to here then return error condition
1613
- return 201;
1614
- }
1615
-
1616
- int timedata(Project *pr)
1617
- /*
1618
- **--------------------------------------------------------------
1619
- ** Input: none
1620
- ** Output: returns error code
1621
- ** Purpose: processes time options data
1622
- ** Formats:
1623
- ** STATISTIC {NONE/AVERAGE/MIN/MAX/RANGE}
1624
- ** DURATION value (units)
1625
- ** HYDRAULIC TIMESTEP value (units)
1626
- ** QUALITY TIMESTEP value (units)
1627
- ** MINIMUM TRAVELTIME value (units)
1628
- ** RULE TIMESTEP value (units)
1629
- ** PATTERN TIMESTEP value (units)
1630
- ** PATTERN START value (units)
1631
- ** REPORT TIMESTEP value (units)
1632
- ** REPORT START value (units)
1633
- ** START CLOCKTIME value (AM PM)
1634
- **-------------------------------------------------------------
1635
- */
1636
- {
1637
- Report *rpt = &pr->report;
1638
- Parser *parser = &pr->parser;
1639
- Times *time = &pr->times;
1640
-
1641
- int n;
1642
- long t;
1643
- double y;
1644
-
1645
- n = parser->Ntokens - 1;
1646
- if (n < 1) return 201;
1647
-
1648
- // Check if setting report time statistic flag
1649
- if (match(parser->Tok[0], w_STATISTIC))
1650
- {
1651
- if (match(parser->Tok[n], w_NONE)) rpt->Tstatflag = SERIES;
1652
- else if (match(parser->Tok[n], w_NO)) rpt->Tstatflag = SERIES;
1653
- else if (match(parser->Tok[n], w_AVG)) rpt->Tstatflag = AVG;
1654
- else if (match(parser->Tok[n], w_MIN)) rpt->Tstatflag = MIN;
1655
- else if (match(parser->Tok[n], w_MAX)) rpt->Tstatflag = MAX;
1656
- else if (match(parser->Tok[n], w_RANGE)) rpt->Tstatflag = RANGE;
1657
- else return setError(parser, n, 213);
1658
- return 0;
1659
- }
1660
-
1661
- // Convert text time value to numerical value in seconds
1662
- // Examples:
1663
- // 5 = 5 * 3600 sec
1664
- // 5 MINUTES = 5 * 60 sec
1665
- // 13:50 = 13*3600 + 50*60 sec
1666
- // 1:50 pm = (12+1)*3600 + 50*60 sec
1667
-
1668
- if (!getfloat(parser->Tok[n], &y))
1669
- {
1670
- if ((y = hour(parser->Tok[n], "")) < 0.0)
1671
- {
1672
- if ((y = hour(parser->Tok[n - 1], parser->Tok[n])) < 0.0)
1673
- {
1674
- return setError(parser, n-1, 213);
1675
- }
1676
- }
1677
- }
1678
- t = (long)(3600.0 * y + 0.5);
1679
-
1680
- /// Process the value assigned to the matched parameter
1681
- if (match(parser->Tok[0], w_DURATION)) time->Dur = t;
1682
- else if (match(parser->Tok[0], w_HYDRAULIC)) time->Hstep = t;
1683
- else if (match(parser->Tok[0], w_QUALITY) ) time->Qstep = t;
1684
- else if (match(parser->Tok[0], w_RULE)) time->Rulestep = t;
1685
- else if (match(parser->Tok[0], w_MINIMUM)) return 0; // Not used anymore
1686
- else if (match(parser->Tok[0], w_PATTERN))
1687
- {
1688
- if (match(parser->Tok[1], w_TIME)) time->Pstep = t;
1689
- else if (match(parser->Tok[1], w_START)) time->Pstart = t;
1690
- else return setError(parser, 1, 213);
1691
- }
1692
- else if (match(parser->Tok[0], w_REPORT))
1693
- {
1694
- if (match(parser->Tok[1], w_TIME)) time->Rstep = t;
1695
- else if (match(parser->Tok[1], w_START)) time->Rstart = t;
1696
- else return setError(parser, 1, 213);
1697
- }
1698
- else if (match(parser->Tok[0], w_START)) time->Tstart = t % SECperDAY;
1699
- else return setError(parser, 0, 213);
1700
- return 0;
1701
- }
1702
-
1703
- int optiondata(Project *pr)
1704
- /*
1705
- **--------------------------------------------------------------
1706
- ** Input: none
1707
- ** Output: returns error code
1708
- ** Purpose: processes [OPTIONS] data
1709
- **--------------------------------------------------------------
1710
- */
1711
- {
1712
- int i, n;
1713
- Parser *parser = &pr->parser;
1714
-
1715
- // Option is a named choice
1716
- n = parser->Ntokens - 1;
1717
- i = optionchoice(pr, n);
1718
- if (i >= 0) return i;
1719
-
1720
- // Option is a numerical value
1721
- return (optionvalue(pr, n));
1722
- }
1723
-
1724
- int optionchoice(Project *pr, int n)
1725
- /*
1726
- **--------------------------------------------------------------
1727
- ** Input: n = index of last input token
1728
- ** Output: returns error code or 0 if option belongs to
1729
- ** those listed below, or -1 otherwise
1730
- ** Purpose: processes fixed choice [OPTIONS] data
1731
- ** Formats:
1732
- ** UNITS CFS/GPM/MGD/IMGD/AFD/LPS/LPM/MLD/CMH/CMD/SI
1733
- ** PRESSURE PSI/KPA/M
1734
- ** HEADLOSS H-W/D-W/C-M
1735
- ** HYDRAULICS USE/SAVE filename
1736
- ** QUALITY NONE/AGE/TRACE/CHEMICAL (TraceNode)
1737
- ** MAP filename
1738
- ** VERIFY filename
1739
- ** UNBALANCED STOP/CONTINUE {Niter}
1740
- ** PATTERN id
1741
- ** DEMAND MODEL DDA/PDA
1742
- **--------------------------------------------------------------
1743
- */
1744
- {
1745
- Network *net = &pr->network;
1746
- Hydraul *hyd = &pr->hydraul;
1747
- Quality *qual = &pr->quality;
1748
- Parser *parser = &pr->parser;
1749
- Outfile *out = &pr->outfile;
1750
-
1751
- int choice;
1752
-
1753
- // Check if 1st token matches a parameter name and
1754
- // process the input for the matched parameter
1755
- if (n < 0) return 201;
1756
-
1757
- // Flow UNITS
1758
- if (match(parser->Tok[0], w_UNITS))
1759
- {
1760
- if (n < 1) return 0;
1761
- else if (match(parser->Tok[1], w_CFS)) parser->Flowflag = CFS;
1762
- else if (match(parser->Tok[1], w_GPM)) parser->Flowflag = GPM;
1763
- else if (match(parser->Tok[1], w_AFD)) parser->Flowflag = AFD;
1764
- else if (match(parser->Tok[1], w_MGD)) parser->Flowflag = MGD;
1765
- else if (match(parser->Tok[1], w_IMGD)) parser->Flowflag = IMGD;
1766
- else if (match(parser->Tok[1], w_LPS)) parser->Flowflag = LPS;
1767
- else if (match(parser->Tok[1], w_LPM)) parser->Flowflag = LPM;
1768
- else if (match(parser->Tok[1], w_CMH)) parser->Flowflag = CMH;
1769
- else if (match(parser->Tok[1], w_CMD)) parser->Flowflag = CMD;
1770
- else if (match(parser->Tok[1], w_MLD)) parser->Flowflag = MLD;
1771
- else if (match(parser->Tok[1], w_SI)) parser->Flowflag = LPS;
1772
- else return setError(parser, 1, 213);
1773
- }
1774
-
1775
- // PRESSURE units
1776
- else if (match(parser->Tok[0], w_PRESSURE))
1777
- {
1778
- if (n < 1) return 0;
1779
- else if (match(parser->Tok[1], w_EXPONENT)) return -1;
1780
- else if (match(parser->Tok[1], w_PSI)) parser->Pressflag = PSI;
1781
- else if (match(parser->Tok[1], w_KPA)) parser->Pressflag = KPA;
1782
- else if (match(parser->Tok[1], w_METERS)) parser->Pressflag = METERS;
1783
- else return setError(parser, 1, 213);
1784
- }
1785
-
1786
- // HEADLOSS formula
1787
- else if (match(parser->Tok[0], w_HEADLOSS))
1788
- {
1789
- if (n < 1) return 0;
1790
- else if (match(parser->Tok[1], w_HW)) hyd->Formflag = HW;
1791
- else if (match(parser->Tok[1], w_DW)) hyd->Formflag = DW;
1792
- else if (match(parser->Tok[1], w_CM)) hyd->Formflag = CM;
1793
- else return setError(parser, 1, 213);
1794
- }
1795
-
1796
- // HYDRUALICS USE/SAVE file option
1797
- else if (match(parser->Tok[0], w_HYDRAULIC))
1798
- {
1799
- if (n < 2) return 0;
1800
- else if (match(parser->Tok[1], w_USE)) out->Hydflag = USE;
1801
- else if (match(parser->Tok[1], w_SAVE)) out->Hydflag = SAVE;
1802
- else return setError(parser, 1, 213);
1803
- strncpy(out->HydFname, parser->Tok[2], MAXFNAME);
1804
- }
1805
-
1806
- // Water QUALITY option
1807
- else if (match(parser->Tok[0], w_QUALITY))
1808
- {
1809
- if (n < 1) return 0;
1810
- else if (match(parser->Tok[1], w_NONE)) qual->Qualflag = NONE;
1811
- else if (match(parser->Tok[1], w_CHEM)) qual->Qualflag = CHEM;
1812
- else if (match(parser->Tok[1], w_AGE)) qual->Qualflag = AGE;
1813
- else if (match(parser->Tok[1], w_TRACE)) qual->Qualflag = TRACE;
1814
- else
1815
- {
1816
- qual->Qualflag = CHEM;
1817
- strncpy(qual->ChemName, parser->Tok[1], MAXID);
1818
- if (n >= 2) strncpy(qual->ChemUnits, parser->Tok[2], MAXID);
1819
- }
1820
- if (qual->Qualflag == TRACE)
1821
- {
1822
- // Copy Trace Node ID to parser->Tok[0] for error reporting
1823
- strcpy(parser->Tok[0], "");
1824
- if (n < 2) return 201;
1825
- strcpy(parser->Tok[0], parser->Tok[2]);
1826
- qual->TraceNode = findnode(net, parser->Tok[2]);
1827
- if (qual->TraceNode == 0) return setError(parser, 2, 212);
1828
- strncpy(qual->ChemName, u_PERCENT, MAXID);
1829
- strncpy(qual->ChemUnits, parser->Tok[2], MAXID);
1830
- }
1831
- if (qual->Qualflag == AGE)
1832
- {
1833
- strncpy(qual->ChemName, w_AGE, MAXID);
1834
- strncpy(qual->ChemUnits, u_HOURS, MAXID);
1835
- }
1836
- }
1837
-
1838
- // MAP file name
1839
- else if (match(parser->Tok[0], w_MAP))
1840
- {
1841
- if (n < 1) return 0;
1842
- strncpy(pr->MapFname, parser->Tok[1], MAXFNAME);
1843
- }
1844
-
1845
- else if (match(parser->Tok[0], w_VERIFY))
1846
- {
1847
- // Deprecated
1848
- }
1849
-
1850
- // Hydraulics UNBALANCED option
1851
- else if (match(parser->Tok[0], w_UNBALANCED))
1852
- {
1853
- if (n < 1) return 0;
1854
- if (match(parser->Tok[1], w_STOP)) hyd->ExtraIter = -1;
1855
- else if (match(parser->Tok[1], w_CONTINUE))
1856
- {
1857
- if (n >= 2) hyd->ExtraIter = atoi(parser->Tok[2]);
1858
- else hyd->ExtraIter = 0;
1859
- }
1860
- else return setError(parser, 1, 213);
1861
- }
1862
-
1863
- // Default demand PATTERN
1864
- else if (match(parser->Tok[0], w_PATTERN))
1865
- {
1866
- if (n < 1) return 0;
1867
- strncpy(parser->DefPatID, parser->Tok[1], MAXID);
1868
- }
1869
-
1870
- // DEMAND model
1871
- else if (match(parser->Tok[0], w_DEMAND))
1872
- {
1873
- if (n < 2) return 0;
1874
- if (!match(parser->Tok[1], w_MODEL)) return -1;
1875
- choice = findmatch(parser->Tok[2], DemandModelTxt);
1876
- if (choice < 0) return setError(parser, 2, 213);
1877
- hyd->DemandModel = choice;
1878
- }
1879
-
1880
- // Return -1 if keyword did not match any option
1881
- else return -1;
1882
- return 0;
1883
- }
1884
-
1885
- int optionvalue(Project *pr, int n)
1886
- /*
1887
- **-------------------------------------------------------------
1888
- ** Input: *line = line read from input file
1889
- ** Output: returns error code
1890
- ** Purpose: processes numerical value [OPTIONS] data
1891
- ** Formats:
1892
- ** DEMAND MULTIPLIER value
1893
- ** EMITTER EXPONENT value
1894
- ** VISCOSITY value
1895
- ** DIFFUSIVITY value
1896
- ** SPECIFIC GRAVITY value
1897
- ** TRIALS value
1898
- ** ACCURACY value
1899
-
1900
- ** HEADERROR value
1901
- ** FLOWCHANGE value
1902
- ** MINIMUM PRESSURE value
1903
- ** REQUIRED PRESSURE value
1904
- ** PRESSURE EXPONENT value
1905
-
1906
- ** TOLERANCE value
1907
- ** SEGMENTS value (not used)
1908
- ** ------ Undocumented Options -----
1909
- ** HTOL value
1910
- ** QTOL value
1911
- ** RQTOL value
1912
- ** CHECKFREQ value
1913
- ** MAXCHECK value
1914
- ** DAMPLIMIT value
1915
- **--------------------------------------------------------------
1916
- */
1917
- {
1918
- Hydraul *hyd = &pr->hydraul;
1919
- Quality *qual = &pr->quality;
1920
- Parser *parser = &pr->parser;
1921
-
1922
- int nvalue = 1; // Index of token with numerical value
1923
- double y;
1924
- char* tok0 = parser->Tok[0];
1925
-
1926
- // Check for deprecated SEGMENTS keyword
1927
- if (match(tok0, w_SEGMENTS)) return 0;
1928
-
1929
- // Check for missing value (which is permissible)
1930
- if (match(tok0, w_SPECGRAV) || match(tok0, w_EMITTER) ||
1931
- match(tok0, w_DEMAND) || match(tok0, w_MINIMUM) ||
1932
- match(tok0, w_REQUIRED) || match(tok0, w_PRESSURE) ||
1933
- match(tok0, w_PRECISION)
1934
- ) nvalue = 2;
1935
- if (n < nvalue) return 0;
1936
-
1937
- // Check for valid numerical input
1938
- if (!getfloat(parser->Tok[nvalue], &y)) return setError(parser, nvalue, 202);
1939
-
1940
- // Quality tolerance option (which can be 0)
1941
- if (match(tok0, w_TOLERANCE))
1942
- {
1943
- if (y < 0.0) return setError(parser, nvalue, 213);
1944
- qual->Ctol = y;
1945
- return 0;
1946
- }
1947
-
1948
- // Diffusivity
1949
- if (match(tok0, w_DIFFUSIVITY))
1950
- {
1951
- if (y < 0.0) return setError(parser, nvalue, 213);
1952
- qual->Diffus = y;
1953
- return 0;
1954
- }
1955
-
1956
- // Hydraulic damping limit option */
1957
- if (match(tok0, w_DAMPLIMIT))
1958
- {
1959
- hyd->DampLimit = y;
1960
- return 0;
1961
- }
1962
-
1963
- // Flow change limit
1964
- else if (match(tok0, w_FLOWCHANGE))
1965
- {
1966
- if (y < 0.0) return setError(parser, nvalue, 213);
1967
- hyd->FlowChangeLimit = y;
1968
- return 0;
1969
- }
1970
-
1971
- // Head loss error limit
1972
- else if (match(tok0, w_HEADERROR))
1973
- {
1974
- if (y < 0.0) return setError(parser, nvalue, 213);
1975
- hyd->HeadErrorLimit = y;
1976
- return 0;
1977
- }
1978
-
1979
- // Pressure dependent demand parameters
1980
- else if (match(tok0, w_MINIMUM))
1981
- {
1982
- if (y < 0.0) return setError(parser, nvalue, 213);
1983
- // Required pressure still at default value
1984
- if (hyd->Preq == MINPDIFF)
1985
- hyd->Preq = y + MINPDIFF;
1986
- // Required pressure already entered
1987
- else if (hyd->Preq - y < MINPDIFF)
1988
- return setError(parser, nvalue, 208);
1989
- hyd->Pmin = y;
1990
- return 0;
1991
- }
1992
- else if (match(tok0, w_REQUIRED))
1993
- {
1994
- if (y < 0.0) return setError(parser, nvalue, 213);
1995
- if (y - hyd->Pmin < MINPDIFF)
1996
- return setError(parser, nvalue, 208);
1997
- hyd->Preq = y;
1998
- return 0;
1999
- }
2000
- else if (match(tok0, w_PRESSURE))
2001
- {
2002
- if (y < 0.0) return setError(parser, nvalue, 213);
2003
- hyd->Pexp = y;
2004
- return 0;
2005
- }
2006
-
2007
- // All other options must be > 0
2008
- if (y <= 0.0) return setError(parser, nvalue, 213);
2009
-
2010
- // Assign value to all other options
2011
- if (match(tok0, w_VISCOSITY)) hyd->Viscos = y;
2012
- else if (match(tok0, w_SPECGRAV)) hyd->SpGrav = y;
2013
- else if (match(tok0, w_TRIALS)) hyd->MaxIter = (int)y;
2014
- else if (match(tok0, w_ACCURACY))
2015
- {
2016
- y = MAX(y, 1.e-5);
2017
- y = MIN(y, 1.e-1);
2018
- hyd->Hacc = y;
2019
- }
2020
- else if (match(tok0, w_HTOL)) hyd->Htol = y;
2021
- else if (match(tok0, w_QTOL)) hyd->Qtol = y;
2022
- else if (match(tok0, w_RQTOL))
2023
- {
2024
- if (y >= 1.0) return 213;
2025
- hyd->RQtol = y;
2026
- }
2027
- else if (match(tok0, w_CHECKFREQ)) hyd->CheckFreq = (int)y;
2028
- else if (match(tok0, w_MAXCHECK)) hyd->MaxCheck = (int)y;
2029
- else if (match(tok0, w_EMITTER)) hyd->Qexp = 1.0 / y;
2030
- else if (match(tok0, w_DEMAND)) hyd->Dmult = y;
2031
- else return 201;
2032
- return 0;
2033
- }
2034
-
2035
- int getpumpcurve(Project *pr, int n)
2036
- /*
2037
- **--------------------------------------------------------
2038
- ** Input: n = number of parameters for pump curve
2039
- ** Output: returns error code
2040
- ** Purpose: processes pump curve data for Version 1.1-
2041
- ** style input data
2042
- ** Notes:
2043
- ** 1. Called by pumpdata() in INPUT3.C
2044
- ** 2. Current link index & pump index of pump being
2045
- ** processed is found in network variables Nlinks
2046
- ** and Npumps, respectively
2047
- ** 3. Curve data read from input line is found in
2048
- ** parser's array X[0],...X[n-1]
2049
- **---------------------------------------------------------
2050
- */
2051
- {
2052
- Network *net = &pr->network;
2053
- Parser *parser = &pr->parser;
2054
-
2055
- double a, b, c, h0, h1, h2, q1, q2;
2056
- Spump *pump = &net->Pump[net->Npumps];
2057
-
2058
- // Constant HP curve
2059
- if (n == 1)
2060
- {
2061
- if (parser->X[0] <= 0.0) return 202;
2062
- pump->Ptype = CONST_HP;
2063
- net->Link[net->Nlinks].Km = parser->X[0];
2064
- }
2065
-
2066
- // Power function curve
2067
- else
2068
- {
2069
- // Single point power curve
2070
- if (n == 2)
2071
- {
2072
- q1 = parser->X[1];
2073
- h1 = parser->X[0];
2074
- h0 = 1.33334 * h1;
2075
- q2 = 2.0 * q1;
2076
- h2 = 0.0;
2077
- }
2078
-
2079
- // 3-point power curve
2080
- else if (n >= 5)
2081
- {
2082
- h0 = parser->X[0];
2083
- h1 = parser->X[1];
2084
- q1 = parser->X[2];
2085
- h2 = parser->X[3];
2086
- q2 = parser->X[4];
2087
- }
2088
- else return 202;
2089
- pump->Ptype = POWER_FUNC;
2090
- if (!powercurve(h0, h1, h2, q1, q2, &a, &b, &c)) return 206;
2091
- pump->H0 = -a;
2092
- pump->R = -b;
2093
- pump->N = c;
2094
- pump->Q0 = q1;
2095
- pump->Qmax = pow((-a / b), (1.0 / c));
2096
- pump->Hmax = h0;
2097
- }
2098
- return 0;
2099
- }
2100
-
2101
- int powercurve(double h0, double h1, double h2, double q1, double q2,
2102
- double *a, double *b, double *c)
2103
- /*
2104
- **---------------------------------------------------------
2105
- ** Input: h0 = shutoff head
2106
- ** h1 = design head
2107
- ** h2 = head at max. flow
2108
- ** q1 = design flow
2109
- ** q2 = max. flow
2110
- ** Output: *a, *b, *c = pump curve coeffs. (H = a-bQ^c),
2111
- ** Returns 1 if sucessful, 0 otherwise.
2112
- ** Purpose: computes coeffs. for pump curve
2113
- **----------------------------------------------------------
2114
- */
2115
- {
2116
- double h4, h5;
2117
-
2118
- if (h0 < TINY || h0 - h1 < TINY || h1 - h2 < TINY ||
2119
- q1 < TINY || q2 - q1 < TINY
2120
- ) return 0;
2121
- *a = h0;
2122
- h4 = h0 - h1;
2123
- h5 = h0 - h2;
2124
- *c = log(h5 / h4) / log(q2 / q1);
2125
- if (*c <= 0.0 || *c > 20.0) return 0;
2126
- *b = -h4 / pow(q1, *c);
2127
- if (*b >= 0.0) return 0;
2128
- return 1;
2129
- }
2130
-
2131
- void changestatus(Network *net, int j, StatusType status, double y)
2132
- /*
2133
- **--------------------------------------------------------------
2134
- ** Input: j = link index
2135
- ** status = status setting (OPEN, CLOSED)
2136
- ** y = numerical setting (pump speed, valve
2137
- ** setting)
2138
- ** Output: none
2139
- ** Purpose: changes status or setting of a link
2140
- **
2141
- ** NOTE: If status = ACTIVE, then a numerical setting (y) was
2142
- ** supplied. If status = OPEN/CLOSED, then numerical
2143
- ** setting is 0.
2144
- **--------------------------------------------------------------
2145
- */
2146
- {
2147
- Slink *link = &net->Link[j];
2148
-
2149
- if (link->Type == PIPE || link->Type == GPV)
2150
- {
2151
- if (status != ACTIVE) link->Status = status;
2152
- }
2153
- else if (link->Type == PUMP)
2154
- {
2155
- if (status == ACTIVE)
2156
- {
2157
- link->Kc = y;
2158
- status = OPEN;
2159
- if (y == 0.0) status = CLOSED;
2160
- }
2161
- else if (status == OPEN) link->Kc = 1.0;
2162
- link->Status = status;
2163
- }
2164
- else if (link->Type >= PRV)
2165
- {
2166
- link->Kc = y;
2167
- link->Status = status;
2168
- if (status != ACTIVE) link->Kc = MISSING;
2169
- }
2170
- }