epyt-flow 0.14.1__py3-none-any.whl → 0.14.2__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 (55) hide show
  1. epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS +8 -40
  2. epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +3 -3
  3. epyt_flow/EPANET/EPANET/SRC_engines/Readme_SRC_Engines.txt +18 -0
  4. epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +7 -24
  5. epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +374 -726
  6. epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +32 -128
  7. epyt_flow/EPANET/EPANET/SRC_engines/epanet2.def +131 -0
  8. epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +1 -7
  9. epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +14 -40
  10. epyt_flow/EPANET/EPANET/SRC_engines/hash.c +177 -177
  11. epyt_flow/EPANET/EPANET/SRC_engines/hash.h +28 -28
  12. epyt_flow/EPANET/EPANET/SRC_engines/hydcoeffs.c +40 -192
  13. epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +46 -101
  14. epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +24 -85
  15. epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +63 -29
  16. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +37 -70
  17. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +234 -408
  18. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +37 -87
  19. epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +79 -153
  20. epyt_flow/EPANET/EPANET/SRC_engines/input1.c +94 -59
  21. epyt_flow/EPANET/EPANET/SRC_engines/input2.c +202 -73
  22. epyt_flow/EPANET/EPANET/SRC_engines/input3.c +351 -446
  23. epyt_flow/EPANET/EPANET/SRC_engines/main.c +93 -0
  24. epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +4 -8
  25. epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +23 -23
  26. epyt_flow/EPANET/EPANET/SRC_engines/output.c +4 -5
  27. epyt_flow/EPANET/EPANET/SRC_engines/project.c +75 -407
  28. epyt_flow/EPANET/EPANET/SRC_engines/quality.c +2 -12
  29. epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +13 -70
  30. epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +5 -7
  31. epyt_flow/EPANET/EPANET/SRC_engines/report.c +20 -88
  32. epyt_flow/EPANET/EPANET/SRC_engines/rules.c +6 -144
  33. epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +19 -19
  34. epyt_flow/EPANET/EPANET/SRC_engines/text.h +5 -16
  35. epyt_flow/EPANET/EPANET/SRC_engines/types.h +19 -73
  36. epyt_flow/EPANET/compile_linux.sh +1 -1
  37. epyt_flow/EPANET/compile_macos.sh +1 -1
  38. epyt_flow/VERSION +1 -1
  39. epyt_flow/simulation/scada/scada_data.py +1 -1
  40. epyt_flow/utils.py +66 -0
  41. epyt_flow/visualization/visualization_utils.py +4 -2
  42. {epyt_flow-0.14.1.dist-info → epyt_flow-0.14.2.dist-info}/METADATA +1 -1
  43. {epyt_flow-0.14.1.dist-info → epyt_flow-0.14.2.dist-info}/RECORD +46 -52
  44. epyt_flow/EPANET/EPANET/SRC_engines/flowbalance.c +0 -186
  45. epyt_flow/EPANET/EPANET/SRC_engines/leakage.c +0 -527
  46. epyt_flow/EPANET/EPANET/SRC_engines/util/cstr_helper.c +0 -59
  47. epyt_flow/EPANET/EPANET/SRC_engines/util/cstr_helper.h +0 -38
  48. epyt_flow/EPANET/EPANET/SRC_engines/util/errormanager.c +0 -92
  49. epyt_flow/EPANET/EPANET/SRC_engines/util/errormanager.h +0 -39
  50. epyt_flow/EPANET/EPANET/SRC_engines/util/filemanager.c +0 -212
  51. epyt_flow/EPANET/EPANET/SRC_engines/util/filemanager.h +0 -81
  52. epyt_flow/EPANET/EPANET/SRC_engines/validate.c +0 -408
  53. {epyt_flow-0.14.1.dist-info → epyt_flow-0.14.2.dist-info}/WHEEL +0 -0
  54. {epyt_flow-0.14.1.dist-info → epyt_flow-0.14.2.dist-info}/licenses/LICENSE +0 -0
  55. {epyt_flow-0.14.1.dist-info → epyt_flow-0.14.2.dist-info}/top_level.txt +0 -0
@@ -1,13 +1,13 @@
1
1
  /*
2
2
  ******************************************************************************
3
3
  Project: OWA EPANET
4
- Version: 2.3
4
+ Version: 2.2
5
5
  Module: input3.c
6
6
  Description: parses network data from a line of an EPANET input file
7
7
  Authors: see AUTHORS
8
8
  Copyright: see AUTHORS
9
9
  License: see LICENSE
10
- Last Updated: 04/19/2025
10
+ Last Updated: 11/29/2019
11
11
  ******************************************************************************
12
12
  */
13
13
 
@@ -25,18 +25,16 @@ Last Updated: 04/19/2025
25
25
  extern char *MixTxt[];
26
26
  extern char *Fldname[];
27
27
  extern char *DemandModelTxt[];
28
- extern char *BackflowTxt[];
29
- extern char *CurveTypeTxt[];
28
+
29
+ // Exported functions
30
+ int powercurve(double, double, double, double, double, double *, double *,
31
+ double *);
30
32
 
31
33
  // Imported Functions
32
34
  extern int addnodeID(Network *, int, char *);
33
35
  extern int addlinkID(Network *, int, char *);
34
- extern int getunitsoption(Project *, char *);
35
- extern int getheadlossoption(Project *, char *);
36
36
 
37
37
  // Local functions
38
- static double gettokvalue(Project *, double, int, int *, int *);
39
- static int getlinknodes(Project *, int *, int *);
40
38
  static int optionchoice(Project *, int);
41
39
  static int optionvalue(Project *, int);
42
40
  static int getpumpcurve(Project *, int);
@@ -78,52 +76,31 @@ int juncdata(Project *pr)
78
76
  int p = 0; // time pattern index
79
77
  int n; // number of tokens
80
78
  int njuncs; // number of network junction nodes
81
- double el = 0.0, // elevation
82
- d = 0.0, // base demand
83
- x;
79
+ double el, // elevation
80
+ y = 0.0; // base demand
84
81
  Snode *node;
85
- int errcode = 0;
86
- int errtok = -1;
82
+ int err = 0;
87
83
 
88
84
  // Add new junction to data base
85
+ n = parser->Ntokens;
89
86
  if (net->Nnodes == parser->MaxNodes) return 200;
90
- errcode = addnodeID(net, net->Njuncs + 1, parser->Tok[0]);
91
- if (errcode > 0) return setError(parser, 0, errcode);
92
87
  net->Njuncs++;
93
88
  net->Nnodes++;
89
+ njuncs = net->Njuncs;
90
+ err = addnodeID(net, net->Njuncs, parser->Tok[0]);
91
+ if (err) return setError(parser, 0, err);
94
92
 
95
93
  // Check for valid data
96
- n = parser->Ntokens;
97
- if (n > 1)
98
- {
99
- if (!getfloat(parser->Tok[1], &x))
100
- {
101
- errcode = 202;
102
- errtok = 1;
103
- }
104
- else el = x;
105
- }
106
- if (!errcode && n > 2)
107
- {
108
- if (!getfloat(parser->Tok[2], &x))
109
- {
110
- errcode = 202;
111
- errtok = 2;
112
- }
113
- else d = x;
114
- }
115
- if (!errcode && n > 3)
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)
116
98
  {
117
99
  p = findpattern(net, parser->Tok[3]);
118
- if (p < 0)
119
- {
120
- errcode = 205;
121
- errtok = 3;
122
- }
100
+ if (p < 0) return setError(parser, 3, 205);
123
101
  }
124
102
 
125
103
  // Save junction data
126
- njuncs = net->Njuncs;
127
104
  node = &net->Node[njuncs];
128
105
  node->X = MISSING;
129
106
  node->Y = MISSING;
@@ -138,14 +115,11 @@ int juncdata(Project *pr)
138
115
 
139
116
  // Create a demand for the junction and use NodeDemand as an indicator
140
117
  // to be used when processing demands from the [DEMANDS] section
141
- if (!adddemand(node, d, p, NULL)) return 101;
142
- hyd->NodeDemand[njuncs] = d;
143
-
144
- // Return error code
145
- if (errcode > 0) return setError(parser, errtok, errcode);
118
+ if (!adddemand(node, y, p, NULL)) return 101;
119
+ hyd->NodeDemand[njuncs] = y;
146
120
  return 0;
147
121
  }
148
-
122
+
149
123
  int tankdata(Project *pr)
150
124
  /*
151
125
  **--------------------------------------------------------------
@@ -156,6 +130,7 @@ int tankdata(Project *pr)
156
130
  ** [RESERVOIRS]
157
131
  ** id elev (pattern)
158
132
  ** [TANKS]
133
+ ** id elev (pattern)
159
134
  ** id elev initlevel minlevel maxlevel diam (minvol vcurve)
160
135
  **--------------------------------------------------------------
161
136
  */
@@ -179,84 +154,68 @@ int tankdata(Project *pr)
179
154
  Snode *node;
180
155
  Stank *tank;
181
156
 
182
- int errcode = 0;
183
- int errtok = -1;
184
- double x;
157
+ int err = 0;
185
158
 
186
159
  // Add new tank to data base
160
+ n = parser->Ntokens;
187
161
  if (net->Ntanks == parser->MaxTanks ||
188
162
  net->Nnodes == parser->MaxNodes) return 200;
189
- i = parser->MaxJuncs + net->Ntanks + 1;
190
- errcode = addnodeID(net, i, parser->Tok[0]);
191
- if (errcode) return setError(parser, 0, errcode);
192
163
  net->Ntanks++;
193
164
  net->Nnodes++;
194
165
 
166
+ i = parser->MaxJuncs + net->Ntanks;
167
+ err = addnodeID(net, i, parser->Tok[0]);
168
+ if (err) return setError(parser, 0, err);
169
+
195
170
  // Check for valid data
196
- n = parser->Ntokens;
197
- if (n < 2) errcode = 201;
198
- if (!errcode && !getfloat(parser->Tok[1], &x))
199
- {
200
- errcode = 202;
201
- errtok = 1;
202
- }
203
- else el = x;
171
+ if (n < 2) return 201;
172
+ if (!getfloat(parser->Tok[1], &el)) return setError(parser, 1, 202);
204
173
 
205
- // Node is a reservoir
174
+ // Tank is reservoir
206
175
  if (n <= 3)
207
176
  {
208
177
  // Head pattern supplied
209
- if (n == 3 && !errcode)
178
+ if (n == 3)
210
179
  {
211
180
  pattern = findpattern(net, parser->Tok[2]);
212
- if (pattern < 0)
213
- {
214
- errcode = 205;
215
- errtok = 2;
216
- }
181
+ if (pattern < 0) return setError(parser, 2, 205);
217
182
  }
218
183
  }
219
-
220
- // Node is a storage tank
221
- else if (!errcode)
184
+ else if (n < 6) return 201;
185
+
186
+ // Tank is a storage tank
187
+ else
222
188
  {
223
- if (n < 6) errcode = 201;
224
- else
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)
225
197
  {
226
- // Read required data
227
- initlevel = gettokvalue(pr, initlevel, 2, &errcode, &errtok);
228
- minlevel = gettokvalue(pr, minlevel, 3, &errcode, &errtok);
229
- maxlevel = gettokvalue(pr, maxlevel, 4, &errcode, &errtok);
230
- diam = gettokvalue(pr, diam, 5, &errcode, &errtok);
231
- if (n >= 7) minvol = gettokvalue(pr, minvol, 6, &errcode, &errtok);
232
-
233
- // If volume curve supplied check it exists
234
- if (!errcode && n >= 8)
198
+ if (strlen(parser->Tok[7]) > 0 && *(parser->Tok[7]) != '*')
235
199
  {
236
- if (strlen(parser->Tok[7]) > 0 && *(parser->Tok[7]) != '*')
237
- {
238
- curve = findcurve(net, parser->Tok[7]);
239
- if (curve == 0)
240
- {
241
- errcode = 206;
242
- errtok = 7;
243
- }
244
- else net->Curve[curve].Type = VOLUME_CURVE;
245
- }
200
+ curve = findcurve(net, parser->Tok[7]);
201
+ if (curve == 0) return setError(parser, 7, 206);
202
+ net->Curve[curve].Type = VOLUME_CURVE;
246
203
  }
204
+ }
247
205
 
248
- // Read overflow indicator if present
249
- if (!errcode && n >= 9)
250
- {
251
- if (match(parser->Tok[8], w_YES)) overflow = TRUE;
252
- else if (match(parser->Tok[8], w_NO)) overflow = FALSE;
253
- else
254
- {
255
- errcode = 213;
256
- errtok = 8;
257
- }
258
- }
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);
259
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);
260
219
  }
261
220
  node = &net->Node[i];
262
221
  tank = &net->Tank[net->Ntanks];
@@ -293,39 +252,10 @@ int tankdata(Project *pr)
293
252
 
294
253
  tank->Vcurve = curve;
295
254
  tank->MixModel = MIX1; // Completely mixed
296
- tank->V1frac = 1.0; // Mixing compartment size fraction
297
-
298
- // Return error code
299
- if (errcode > 0) return setError(parser, errtok, errcode);
255
+ tank->V1max = 1.0; // Mixing compartment size fraction
300
256
  return 0;
301
257
  }
302
258
 
303
- double gettokvalue(Project *pr, double x, int itok, int *errcode, int *errtok)
304
- /*
305
- **--------------------------------------------------------------
306
- ** Input: x = default numerical value
307
- ** itok = index into an array of string tokens
308
- ** Output: errcode = an error code or 0 if successful
309
- ** errtok = itok if an error occurs
310
- ** returns a numerical data value
311
- ** Purpose: converts a string token into a numerical value.
312
- **--------------------------------------------------------------
313
- */
314
- {
315
- Parser *parser = &pr->parser;
316
- double result;
317
-
318
- if (*errcode) return x;
319
- if (!getfloat(parser->Tok[itok], &result)) *errcode = 202;
320
- else if (result < 0.0) *errcode = 209;
321
- if (*errcode > 0)
322
- {
323
- result = x;
324
- *errtok = itok;
325
- }
326
- return result;
327
- }
328
-
329
259
  int pipedata(Project *pr)
330
260
  /*
331
261
  **--------------------------------------------------------------
@@ -344,104 +274,71 @@ int pipedata(Project *pr)
344
274
  int j1, // Start-node index
345
275
  j2, // End-node index
346
276
  n; // # data items
347
- double x;
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
348
283
  Slink *link;
349
- int errcode = 0;
350
-
351
- // Check that end nodes exist
352
- if (net->Nlinks == parser->MaxLinks) return 200;
284
+ int err = 0;
285
+
286
+ // Add new pipe to data base
353
287
  n = parser->Ntokens;
354
- if (n < 3) return setError(parser, -1, errcode);
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;
355
296
  if ((j1 = findnode(net, parser->Tok[1])) == 0) return setError(parser, 1, 203);
356
297
  if ((j2 = findnode(net, parser->Tok[2])) == 0) return setError(parser, 2, 203);
357
298
  if (j1 == j2) return setError(parser, 0, 222);
358
299
 
359
- // Add new pipe to data base
360
- errcode = addlinkID(net, net->Nlinks+1, parser->Tok[0]);
361
- if (errcode) return setError(parser, 0, errcode);
362
- net->Npipes++;
363
- net->Nlinks++;
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);
364
306
 
365
- // Assign default data to pipe
366
- link = &net->Link[net->Nlinks];
367
- link->N1 = j1;
368
- link->N2 = j2;
369
-
370
- if (parser->Unitsflag == SI)
307
+ // Either a loss coeff. or a status is supplied
308
+ if (n == 7)
371
309
  {
372
- link->Len = 100.0;
373
- link->Diam = 254.0;
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);
374
314
  }
375
- else
315
+
316
+ // Both a loss coeff. and a status is supplied
317
+ if (n == 8)
376
318
  {
377
- link->Len = 330.0;
378
- link->Diam = 10.0;
379
- }
380
- switch (pr->hydraul.Formflag)
381
- {
382
- case HW: link->Kc = 130; break;
383
- case DW: link->Kc = 0.0005; break;
384
- case CM: link->Kc = 0.01; break;
385
- default: link->Kc = 1.0;
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);
386
324
  }
387
-
388
- link->Km = 0.0;
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;
389
335
  link->Kb = MISSING;
390
336
  link->Kw = MISSING;
391
- link->LeakArea = 0.0;
392
- link->LeakExpan = 0.0;
393
- link->Type = PIPE;
394
- link->InitStatus = OPEN;
395
- link->InitSetting = link->Kc;
337
+ link->Type = type;
338
+ link->Status = status;
396
339
  link->Rpt = 0;
397
340
  link->ResultIndex = 0;
398
341
  link->Comment = xstrcpy(&link->Comment, parser->Comment, MAXMSG);
399
-
400
- // Parse data values from input tokens
401
- if (n > 3)
402
- {
403
- if (!getfloat(parser->Tok[3], &x) || x <= 0.0)
404
- return setError(parser, 3, 202);
405
- link->Len = x;
406
- }
407
- if (n > 4)
408
- {
409
- if (!getfloat(parser->Tok[4], &x) || x <= 0.0)
410
- return setError(parser, 4, 202);
411
- link->Diam = x;
412
- }
413
- if (n > 5)
414
- {
415
- if (!getfloat(parser->Tok[5], &x) || x <= 0.0)
416
- return setError(parser, 5, 202);
417
- link->Kc = x;
418
- }
419
-
420
- // Either a loss coeff. or a status is supplied
421
- if (n > 6)
422
- {
423
- if (match(parser->Tok[6], w_CV)) link->Type = CVPIPE;
424
- else if (match(parser->Tok[6], w_CLOSED)) link->InitStatus = CLOSED;
425
- else if (match(parser->Tok[6], w_OPEN)) link->InitStatus = OPEN;
426
- else
427
- {
428
- if (!getfloat(parser->Tok[6], &x) || x < 0.0)
429
- return setError(parser, 6, 202);
430
- link->Km = x;
431
- }
432
- }
433
-
434
- // Both a loss coeff. and a status is supplied
435
- if (n > 7)
436
- {
437
- if (!getfloat(parser->Tok[6], &x) || x < 0.0)
438
- return setError(parser, 6, 202);
439
- link->Km = x;
440
- if (match(parser->Tok[7], w_CV)) link->Type = CVPIPE;
441
- else if (match(parser->Tok[7], w_CLOSED)) link->InitStatus = CLOSED;
442
- else if (match(parser->Tok[7], w_OPEN)) link->InitStatus = OPEN;
443
- else return setError(parser, 7, 213);
444
- }
445
342
  return 0;
446
343
  }
447
344
 
@@ -453,6 +350,11 @@ int pumpdata(Project *pr)
453
350
  ** Purpose: processes pump data
454
351
  ** Formats:
455
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):
456
358
  ** id node1 node2 KEYWORD value {KEYWORD value ...}
457
359
  ** where KEYWORD = [POWER,HEAD,PATTERN,SPEED]
458
360
  **--------------------------------------------------------------
@@ -461,7 +363,7 @@ int pumpdata(Project *pr)
461
363
  Network *net = &pr->network;
462
364
  Parser *parser = &pr->parser;
463
365
 
464
- int m, // Token array indexes
366
+ int j, m, // Token array indexes
465
367
  j1, // Start-node index
466
368
  j2, // End-node index
467
369
  n, // # data items
@@ -469,24 +371,24 @@ int pumpdata(Project *pr)
469
371
  double y;
470
372
  Slink *link;
471
373
  Spump *pump;
472
- int errcode = 0;
473
-
474
- // Check that end nodes exist
374
+ int err = 0;
375
+
376
+ /* Add new pump to data base */
377
+ n = parser->Ntokens;
475
378
  if (net->Nlinks == parser->MaxLinks ||
476
379
  net->Npumps == parser->MaxPumps) return 200;
477
- n = parser->Ntokens;
478
- if (n < 3) return setError(parser, -1, errcode);
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;
479
387
  if ((j1 = findnode(net, parser->Tok[1])) == 0) return setError(parser, 1, 203);
480
388
  if ((j2 = findnode(net, parser->Tok[2])) == 0) return setError(parser, 2, 203);
481
389
  if (j1 == j2) return setError(parser, 0, 222);
482
390
 
483
- // Add new pump to data base
484
- errcode = addlinkID(net, net->Nlinks+1, parser->Tok[0]);
485
- if (errcode) return setError(parser, 0, errcode);
486
- net->Nlinks++;
487
- net->Npumps++;
488
-
489
- // Assign default data to pump
391
+ // Save pump data
490
392
  link = &net->Link[net->Nlinks];
491
393
  pump = &net->Pump[net->Npumps];
492
394
 
@@ -498,11 +400,8 @@ int pumpdata(Project *pr)
498
400
  link->Km = 0.0;
499
401
  link->Kb = 0.0;
500
402
  link->Kw = 0.0;
501
- link->LeakArea = 0.0;
502
- link->LeakExpan = 0.0;
503
403
  link->Type = PUMP;
504
- link->InitStatus = OPEN;
505
- link->InitSetting = 1.0;
404
+ link->Status = OPEN;
506
405
  link->Rpt = 0;
507
406
  link->ResultIndex = 0;
508
407
  link->Comment = xstrcpy(&link->Comment, parser->Comment, MAXMSG);
@@ -515,14 +414,28 @@ int pumpdata(Project *pr)
515
414
  pump->Epat = 0;
516
415
  if (n < 4) return 0;
517
416
 
518
- // Retrieve keyword/value pairs
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
519
432
  m = 4;
520
433
  while (m < n)
521
434
  {
522
435
  if (match(parser->Tok[m - 1], w_POWER)) // Const. HP curve
523
436
  {
524
- if (!getfloat(parser->Tok[m], &y) || y <= 0.0)
525
- return setError(parser, m, 202);
437
+ y = atof(parser->Tok[m]);
438
+ if (y <= 0.0) return setError(parser, m, 202);
526
439
  pump->Ptype = CONST_HP;
527
440
  link->Km = y;
528
441
  }
@@ -530,7 +443,6 @@ int pumpdata(Project *pr)
530
443
  {
531
444
  c = findcurve(net, parser->Tok[m]);
532
445
  if (c == 0) return setError(parser, m, 206);
533
- pump->Ptype = CUSTOM;
534
446
  pump->Hcurve = c;
535
447
  }
536
448
  else if (match(parser->Tok[m - 1], w_PATTERN)) // Speed/status pattern
@@ -541,14 +453,13 @@ int pumpdata(Project *pr)
541
453
  }
542
454
  else if (match(parser->Tok[m - 1], w_SPEED)) // Speed setting
543
455
  {
544
- if (!getfloat(parser->Tok[m], &y) || y < 0.0)
545
- return setError(parser, m, 202);
456
+ if (!getfloat(parser->Tok[m], &y)) return setError(parser, m, 202);
457
+ if (y < 0.0) return setError(parser, m, 211);
546
458
  link->Kc = y;
547
459
  }
548
- else return setError(parser, m-1, 201);;
460
+ else return 201;
549
461
  m = m + 2; // Move to next keyword token
550
462
  }
551
- link->InitSetting = link->Kc;
552
463
  return 0;
553
464
  }
554
465
 
@@ -560,7 +471,7 @@ int valvedata(Project *pr)
560
471
  ** Purpose: processes valve data
561
472
  ** Format:
562
473
  ** [VALVE]
563
- ** id node1 node2 diam type setting (lcoeff lcurve)
474
+ ** id node1 node2 diam type setting (lcoeff)
564
475
  **--------------------------------------------------------------
565
476
  */
566
477
  {
@@ -573,30 +484,61 @@ int valvedata(Project *pr)
573
484
  n; // # data items
574
485
  char status = ACTIVE, // Valve status
575
486
  type; // Valve type
576
- double x;
487
+ double diam = 0.0, // Valve diameter
488
+ setting, // Valve setting
489
+ lcoeff = 0.0; // Minor loss coeff.
577
490
  Slink *link;
578
- int errcode = 0,
579
- losscurve = 0; // Loss coeff. curve
491
+ int err = 0;
580
492
 
581
- // Check that end nodes exist
493
+ // Add new valve to data base
494
+ n = parser->Ntokens;
582
495
  if (net->Nlinks == parser->MaxLinks ||
583
496
  net->Nvalves == parser->MaxValves) return 200;
584
- n = parser->Ntokens;
585
- if (n < 5) return setError(parser, -1, errcode);
586
- if ((j1 = findnode(net, parser->Tok[1])) == 0) return setError(parser, 1, 203);
587
- if ((j2 = findnode(net, parser->Tok[2])) == 0) return setError(parser, 2, 203);
588
- if (j1 == j2) return setError(parser, 0, 222);
589
-
590
- // Parse valve type
591
- if (match(parser->Tok[4], w_PRV)) type = PRV;
592
- else if (match(parser->Tok[4], w_PSV)) type = PSV;
593
- else if (match(parser->Tok[4], w_PBV)) type = PBV;
594
- else if (match(parser->Tok[4], w_FCV)) type = FCV;
595
- else if (match(parser->Tok[4], w_TCV)) type = TCV;
596
- else if (match(parser->Tok[4], w_GPV)) type = GPV;
597
- else if (match(parser->Tok[4], w_PCV)) type = PCV;
598
- else return setError(parser, 4, 213);
599
-
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
+
600
542
  // Check for illegal connections
601
543
  if (valvecheck(pr, net->Nlinks, type, j1, j2))
602
544
  {
@@ -605,71 +547,22 @@ int valvedata(Project *pr)
605
547
  else return setError(parser, -1, 220);
606
548
  }
607
549
 
608
- // Add new valve to data base
609
- errcode = addlinkID(net, net->Nlinks+1, parser->Tok[0]);
610
- if (errcode) return setError(parser, 0, errcode);
611
- net->Nvalves++;
612
- net->Nlinks++;
613
-
614
- // Assign default data to valve
550
+ // Save valve data
615
551
  link = &net->Link[net->Nlinks];
616
552
  link->N1 = j1;
617
553
  link->N2 = j2;
618
- if (parser->Unitsflag == SI) link->Diam = 254.0;
619
- else link->Diam = 10.0;
554
+ link->Diam = diam;
620
555
  link->Len = 0.0;
621
- link->Kc = 0.0;
622
- link->Km = 0.0;
556
+ link->Kc = setting;
557
+ link->Km = lcoeff;
623
558
  link->Kb = 0.0;
624
559
  link->Kw = 0.0;
625
- link->LeakArea = 0.0;
626
- link->LeakExpan = 0.0;
627
560
  link->Type = type;
628
- link->InitStatus = ACTIVE;
629
- link->InitSetting = 0.0;
561
+ link->Status = status;
630
562
  link->Rpt = 0;
631
563
  link->ResultIndex = 0;
632
564
  link->Comment = xstrcpy(&link->Comment, parser->Comment, MAXMSG);
633
565
  net->Valve[net->Nvalves].Link = net->Nlinks;
634
- net->Valve[net->Nvalves].Curve = 0;
635
-
636
- // Parse data values
637
- if (!getfloat(parser->Tok[3], &x) || x <= 0.0)
638
- return setError(parser, 3, 202);
639
- link->Diam = x;
640
- if (n > 5)
641
- {
642
- // Find headloss curve for GPV
643
- if (type == GPV)
644
- {
645
- c = findcurve(net, parser->Tok[5]);
646
- if (c == 0) return setError(parser, 5, 206);
647
- link->Kc = c;
648
- net->Curve[c].Type = HLOSS_CURVE;
649
- link->InitStatus = OPEN;
650
- }
651
- else
652
- {
653
- if (!getfloat(parser->Tok[5], &x)) return setError(parser, 5, 202);
654
- link->Kc = x;
655
- }
656
- }
657
- if (n > 6)
658
- {
659
- if (!getfloat(parser->Tok[6], &x) || x < 0.0)
660
- return setError(parser, 6, 202);
661
- link->Km = x;
662
- }
663
- if (n > 7 && type == PCV)
664
- {
665
- // Find loss coeff. curve for PCV
666
- c = findcurve(net, parser->Tok[7]);
667
- if (c == 0) return setError(parser, 7, 206);
668
- net->Valve[net->Nvalves].Curve = c;
669
- net->Curve[c].Type = VALVE_CURVE;
670
- if (link->Kc > 100.0) link->Kc = 100.0;
671
- }
672
- link->InitSetting = link->Kc;
673
566
  return 0;
674
567
  }
675
568
 
@@ -720,7 +613,6 @@ int patterndata(Project *pr)
720
613
  pattern->F = realloc(pattern->F, pattern->Length * sizeof(double));
721
614
 
722
615
  // Add parsed multipliers to the pattern
723
- for (j = 1; j <= n; j++) pattern->F[n1 + j - 1] = 1.0;
724
616
  for (j = 1; j <= n; j++)
725
617
  {
726
618
  if (!getfloat(parser->Tok[j], &x)) return setError(parser, j, 202);
@@ -747,7 +639,7 @@ int curvedata(Project *pr)
747
639
  Network *net = &pr->network;
748
640
  Parser *parser = &pr->parser;
749
641
 
750
- int i, ctype;
642
+ int i;
751
643
  double x, y;
752
644
  Scurve *curve;
753
645
 
@@ -755,11 +647,6 @@ int curvedata(Project *pr)
755
647
  if (parser->Ntokens < 3) return 201;
756
648
  if (!getfloat(parser->Tok[1], &x)) return setError(parser, 1, 202);
757
649
  if (!getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
758
- ctype = -1;
759
- if (parser->Ntokens > 3)
760
- {
761
- ctype = findmatch(parser->Tok[3], CurveTypeTxt);
762
- }
763
650
 
764
651
  // Check if previous input line was for the same curve
765
652
  if (parser->PrevCurve && strcmp(parser->Tok[0], parser->PrevCurve->ID) == 0)
@@ -789,7 +676,6 @@ int curvedata(Project *pr)
789
676
  curve->X[curve->Npts] = x;
790
677
  curve->Y[curve->Npts] = y;
791
678
  curve->Npts++;
792
- if (ctype >= 0) curve->Type = (CurveType)ctype;
793
679
 
794
680
  // Save a reference to this curve for processing additional curve data
795
681
  parser->PrevCurve = curve;
@@ -800,14 +686,11 @@ int coordata(Project *pr)
800
686
  /*
801
687
  **--------------------------------------------------------------
802
688
  ** Input: none
803
- ** Output: returns 0
804
- ** Purpose: processes node coordinate data
689
+ ** Output: returns error code
690
+ ** Purpose: processes coordinate data
805
691
  ** Format:
806
692
  ** [COORD]
807
693
  ** id x y
808
- **
809
- ** Note: since node coords. are not used in any computations,
810
- ** invalid data are simply ignored.
811
694
  **--------------------------------------------------------------
812
695
  */
813
696
  {
@@ -819,12 +702,12 @@ int coordata(Project *pr)
819
702
  Snode *node;
820
703
 
821
704
  // Check for valid node ID
822
- if (parser->Ntokens < 3) return 0;
823
- if ((j = findnode(net, parser->Tok[0])) == 0) return 0;
705
+ if (parser->Ntokens < 3) return 201;
706
+ if ((j = findnode(net, parser->Tok[0])) == 0) return setError(parser, 0, 203);
824
707
 
825
708
  // Check for valid data
826
- if (!getfloat(parser->Tok[1], &x)) return 0;
827
- if (!getfloat(parser->Tok[2], &y)) return 0;
709
+ if (!getfloat(parser->Tok[1], &x)) return setError(parser, 1, 202);
710
+ if (!getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
828
711
 
829
712
  // Save coord data
830
713
  node = &net->Node[j];
@@ -837,14 +720,11 @@ int vertexdata(Project *pr)
837
720
  /*
838
721
  **--------------------------------------------------------------
839
722
  ** Input: none
840
- ** Output: returns 0
723
+ ** Output: returns error code
841
724
  ** Purpose: processes link vertex data
842
725
  ** Format:
843
726
  ** [VERTICES]
844
727
  ** id x y
845
- **
846
- ** Note: since vertex coords. are not used in any computations,
847
- ** invalid data are simply ignored.
848
728
  **--------------------------------------------------------------
849
729
  */
850
730
  {
@@ -855,12 +735,12 @@ int vertexdata(Project *pr)
855
735
  double x, y;
856
736
 
857
737
  // Check for valid link ID
858
- if (parser->Ntokens < 3) return 0;
859
- if ((j = findlink(net, parser->Tok[0])) == 0) return 0;
738
+ if (parser->Ntokens < 3) return 201;
739
+ if ((j = findlink(net, parser->Tok[0])) == 0) return setError(parser, 0, 204);
860
740
 
861
741
  // Check for valid coordinate data
862
- if (!getfloat(parser->Tok[1], &x)) return 0;
863
- if (!getfloat(parser->Tok[2], &y)) return 0;
742
+ if (!getfloat(parser->Tok[1], &x)) return setError(parser, 1, 202);
743
+ if (!getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
864
744
 
865
745
  // Add to link's list of vertex points
866
746
  return addlinkvertex(&net->Link[j], x, y);
@@ -875,6 +755,7 @@ int demanddata(Project *pr)
875
755
  ** Purpose: processes node demand data
876
756
  ** Format:
877
757
  ** [DEMANDS]
758
+ ** MULTIPLY factor
878
759
  ** node base_demand (pattern)
879
760
  **
880
761
  ** NOTE: Demands entered in this section replace those
@@ -896,7 +777,15 @@ int demanddata(Project *pr)
896
777
  if (n < 2) return 201;
897
778
  if (!getfloat(parser->Tok[1], &y)) return setError(parser, 1, 202);
898
779
 
899
- // Find node (and pattern) being referenced
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
900
789
  if ((j = findnode(net, parser->Tok[0])) == 0) return setError(parser, 0, 203);
901
790
  if (j > net->Njuncs) return 0;
902
791
  if (n >= 3)
@@ -933,10 +822,10 @@ int controldata(Project *pr)
933
822
  ** Purpose: processes simple controls
934
823
  ** Formats:
935
824
  ** [CONTROLS]
936
- ** LINK linkID setting IF NODE nodeID {BELOW/ABOVE} level (DISABLED)
937
- ** LINK linkID setting AT TIME value (units) (DISABLED)
938
- ** LINK linkID setting AT CLOCKTIME value (units) (DISABLED)
939
- ** (0) (1) (2) (3) (4) (5) (6) (7) (8)
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)
940
829
  **--------------------------------------------------------------
941
830
  */
942
831
  {
@@ -945,8 +834,7 @@ int controldata(Project *pr)
945
834
 
946
835
  int i = 0, // Node index
947
836
  k, // Link index
948
- n, // # data items
949
- isEnabled = TRUE; // Control enabled
837
+ n; // # data items
950
838
  double setting = MISSING, // Link setting
951
839
  time = 0.0, // Simulation time
952
840
  level = 0.0; // Pressure or tank level
@@ -958,13 +846,6 @@ int controldata(Project *pr)
958
846
  // Check for sufficient number of input tokens
959
847
  n = parser->Ntokens;
960
848
  if (n < 6) return 201;
961
-
962
- // Check if last token is "DISABLED"
963
- if (match(parser->Tok[n-1], w_DISABLED))
964
- {
965
- isEnabled = FALSE;
966
- n = n - 1;
967
- }
968
849
 
969
850
  // Check that controlled link exists
970
851
  k = findlink(net, parser->Tok[1]);
@@ -1020,7 +901,7 @@ int controldata(Project *pr)
1020
901
  case TIMER:
1021
902
  case TIMEOFDAY:
1022
903
  if (n == 6) time = hour(parser->Tok[5], "");
1023
- if (n >= 7) time = hour(parser->Tok[5], parser->Tok[6]);
904
+ if (n == 7) time = hour(parser->Tok[5], parser->Tok[6]);
1024
905
  if (time < 0.0) return setError(parser, 5, 213);
1025
906
  break;
1026
907
  case LOWLEVEL:
@@ -1041,7 +922,6 @@ int controldata(Project *pr)
1041
922
  control->Time = (long)(3600.0 * time);
1042
923
  if (ctltype == TIMEOFDAY) control->Time %= SECperDAY;
1043
924
  control->Grade = level;
1044
- control->isEnabled = isEnabled;
1045
925
  return 0;
1046
926
  }
1047
927
 
@@ -1145,41 +1025,6 @@ int emitterdata(Project *pr)
1145
1025
  return 0;
1146
1026
  }
1147
1027
 
1148
- int leakagedata(Project *pr)
1149
- /*
1150
- **--------------------------------------------------------------
1151
- ** Input: none
1152
- ** Output: returns error code
1153
- ** Purpose: processes link leakage data
1154
- ** Format:
1155
- ** [LEAKAGE]
1156
- ** link C1 C2
1157
- **--------------------------------------------------------------
1158
- */
1159
- {
1160
- Network *net = &pr->network;
1161
- Parser *parser = &pr->parser;
1162
-
1163
- int j, // Link index
1164
- n; // # data items
1165
- double c1, c2; // Flow coeff.
1166
-
1167
- // Check that link exists & is a pipe
1168
- n = parser->Ntokens;
1169
- if (n < 3) return 201;
1170
- if ((j = findlink(net, parser->Tok[0])) == 0) return setError(parser, 0, 203);
1171
- if (net->Link[j].Type > PIPE) return 0;
1172
-
1173
- // Parse leakage coeffs.
1174
- if (!getfloat(parser->Tok[1], &c1)) return setError(parser, 1, 202);
1175
- if (c1 < 0.0) return setError(parser, 1, 209);
1176
- if (!getfloat(parser->Tok[2], &c2)) return setError(parser, 2, 202);
1177
- if (c2 < 0.0) return setError(parser, 1, 209);
1178
- net->Link[j].LeakArea = c1;
1179
- net->Link[j].LeakExpan = c2;
1180
- return 0;
1181
- }
1182
-
1183
1028
  int qualdata(Project *pr)
1184
1029
  /*
1185
1030
  **--------------------------------------------------------------
@@ -1443,7 +1288,7 @@ int mixingdata(Project *pr)
1443
1288
  i = j - net->Njuncs;
1444
1289
  if (net->Tank[i].A == 0.0) return 0;
1445
1290
  net->Tank[i].MixModel = (char)m;
1446
- net->Tank[i].V1frac = v;
1291
+ net->Tank[i].V1max = v;
1447
1292
  return 0;
1448
1293
  }
1449
1294
 
@@ -1884,8 +1729,8 @@ int optionchoice(Project *pr, int n)
1884
1729
  ** those listed below, or -1 otherwise
1885
1730
  ** Purpose: processes fixed choice [OPTIONS] data
1886
1731
  ** Formats:
1887
- ** UNITS CFS/GPM/MGD/IMGD/AFD/LPS/LPM/MLD/CMH/CMD/CMS
1888
- ** PRESSURE PSI/KPA/METERS/BAR/FEET
1732
+ ** UNITS CFS/GPM/MGD/IMGD/AFD/LPS/LPM/MLD/CMH/CMD/SI
1733
+ ** PRESSURE PSI/KPA/M
1889
1734
  ** HEADLOSS H-W/D-W/C-M
1890
1735
  ** HYDRAULICS USE/SAVE filename
1891
1736
  ** QUALITY NONE/AGE/TRACE/CHEMICAL (TraceNode)
@@ -1894,7 +1739,6 @@ int optionchoice(Project *pr, int n)
1894
1739
  ** UNBALANCED STOP/CONTINUE {Niter}
1895
1740
  ** PATTERN id
1896
1741
  ** DEMAND MODEL DDA/PDA
1897
- ** BACKFLOW ALLOWED YES/NO
1898
1742
  **--------------------------------------------------------------
1899
1743
  */
1900
1744
  {
@@ -1914,20 +1758,28 @@ int optionchoice(Project *pr, int n)
1914
1758
  if (match(parser->Tok[0], w_UNITS))
1915
1759
  {
1916
1760
  if (n < 1) return 0;
1917
- if (!getunitsoption(pr, parser->Tok[1]))
1918
- return setError(parser, 1, 213);
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);
1919
1773
  }
1920
1774
 
1921
1775
  // PRESSURE units
1922
1776
  else if (match(parser->Tok[0], w_PRESSURE))
1923
1777
  {
1924
- if (n < 1) return 0;
1778
+ if (n < 1) return 0;
1925
1779
  else if (match(parser->Tok[1], w_EXPONENT)) return -1;
1926
1780
  else if (match(parser->Tok[1], w_PSI)) parser->Pressflag = PSI;
1927
1781
  else if (match(parser->Tok[1], w_KPA)) parser->Pressflag = KPA;
1928
1782
  else if (match(parser->Tok[1], w_METERS)) parser->Pressflag = METERS;
1929
- else if (match(parser->Tok[1], w_BAR)) parser->Pressflag = BAR;
1930
- else if (match(parser->Tok[1], w_FEET)) parser->Pressflag = FEET;
1931
1783
  else return setError(parser, 1, 213);
1932
1784
  }
1933
1785
 
@@ -1935,8 +1787,10 @@ int optionchoice(Project *pr, int n)
1935
1787
  else if (match(parser->Tok[0], w_HEADLOSS))
1936
1788
  {
1937
1789
  if (n < 1) return 0;
1938
- if (!getheadlossoption(pr, parser->Tok[1]))
1939
- return setError(parser, 1, 213);
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);
1940
1794
  }
1941
1795
 
1942
1796
  // HYDRUALICS USE/SAVE file option
@@ -1965,7 +1819,10 @@ int optionchoice(Project *pr, int n)
1965
1819
  }
1966
1820
  if (qual->Qualflag == TRACE)
1967
1821
  {
1822
+ // Copy Trace Node ID to parser->Tok[0] for error reporting
1823
+ strcpy(parser->Tok[0], "");
1968
1824
  if (n < 2) return 201;
1825
+ strcpy(parser->Tok[0], parser->Tok[2]);
1969
1826
  qual->TraceNode = findnode(net, parser->Tok[2]);
1970
1827
  if (qual->TraceNode == 0) return setError(parser, 2, 212);
1971
1828
  strncpy(qual->ChemName, u_PERCENT, MAXID);
@@ -2019,16 +1876,6 @@ int optionchoice(Project *pr, int n)
2019
1876
  if (choice < 0) return setError(parser, 2, 213);
2020
1877
  hyd->DemandModel = choice;
2021
1878
  }
2022
-
2023
- // Emitter BACKFLOW ALLOWED
2024
- else if (match(parser->Tok[0], w_BACKFLOW))
2025
- {
2026
- if (n < 2) return 0;
2027
- if (!match(parser->Tok[1], w_ALLOWED)) return -1;
2028
- choice = findmatch(parser->Tok[2], BackflowTxt);
2029
- if (choice < 0) return setError(parser, 2, 213);
2030
- hyd->EmitBackFlag = choice;
2031
- }
2032
1879
 
2033
1880
  // Return -1 if keyword did not match any option
2034
1881
  else return -1;
@@ -2038,7 +1885,7 @@ int optionchoice(Project *pr, int n)
2038
1885
  int optionvalue(Project *pr, int n)
2039
1886
  /*
2040
1887
  **-------------------------------------------------------------
2041
- ** Input: n = index of last input token
1888
+ ** Input: *line = line read from input file
2042
1889
  ** Output: returns error code
2043
1890
  ** Purpose: processes numerical value [OPTIONS] data
2044
1891
  ** Formats:
@@ -2185,43 +2032,102 @@ int optionvalue(Project *pr, int n)
2185
2032
  return 0;
2186
2033
  }
2187
2034
 
2188
- int tagdata(Project *pr)
2035
+ int getpumpcurve(Project *pr, int n)
2189
2036
  /*
2190
- **-------------------------------------------------------------
2191
- ** Input: none
2037
+ **--------------------------------------------------------
2038
+ ** Input: n = number of parameters for pump curve
2192
2039
  ** Output: returns error code
2193
- ** Purpose: processes [TAGS] data
2194
- ** Formats:
2195
- ** NODE id tag
2196
- ** LINK id tag
2197
- **--------------------------------------------------------------
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
+ **---------------------------------------------------------
2198
2050
  */
2199
2051
  {
2200
2052
  Network *net = &pr->network;
2201
2053
  Parser *parser = &pr->parser;
2202
2054
 
2203
- int j, n;
2204
-
2205
- // Check for sufficient data
2206
- n = parser->Ntokens;
2207
- if (n < 3) return 201;
2055
+ double a, b, c, h0, h1, h2, q1, q2;
2056
+ Spump *pump = &net->Pump[net->Npumps];
2208
2057
 
2209
- // First keyword is NODE
2210
- if (match(parser->Tok[0], w_NODE))
2058
+ // Constant HP curve
2059
+ if (n == 1)
2211
2060
  {
2212
- if ((j = findnode(net, parser->Tok[1])) == 0) return setError(parser, 0, 203);
2213
- xstrcpy(&net->Node[j].Tag, parser->Tok[2], MAXMSG);
2061
+ if (parser->X[0] <= 0.0) return 202;
2062
+ pump->Ptype = CONST_HP;
2063
+ net->Link[net->Nlinks].Km = parser->X[0];
2214
2064
  }
2215
2065
 
2216
- // First keyword is LINK
2217
- else if (match(parser->Tok[0], w_LINK))
2066
+ // Power function curve
2067
+ else
2218
2068
  {
2219
- if ((j = findlink(net, parser->Tok[1])) == 0) return setError(parser, 0, 203);
2220
- xstrcpy(&net->Link[j].Tag, parser->Tok[2], MAXMSG);
2221
- }
2222
- return 0;
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;
2223
2099
  }
2224
-
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
+
2225
2131
  void changestatus(Network *net, int j, StatusType status, double y)
2226
2132
  /*
2227
2133
  **--------------------------------------------------------------
@@ -2230,10 +2136,11 @@ void changestatus(Network *net, int j, StatusType status, double y)
2230
2136
  ** y = numerical setting (pump speed, valve
2231
2137
  ** setting)
2232
2138
  ** Output: none
2233
- ** Purpose: changes initial status or setting of a link
2139
+ ** Purpose: changes status or setting of a link
2234
2140
  **
2235
2141
  ** NOTE: If status = ACTIVE, then a numerical setting (y) was
2236
- ** supplied.
2142
+ ** supplied. If status = OPEN/CLOSED, then numerical
2143
+ ** setting is 0.
2237
2144
  **--------------------------------------------------------------
2238
2145
  */
2239
2146
  {
@@ -2241,7 +2148,7 @@ void changestatus(Network *net, int j, StatusType status, double y)
2241
2148
 
2242
2149
  if (link->Type == PIPE || link->Type == GPV)
2243
2150
  {
2244
- if (status != ACTIVE) link->InitStatus = status;
2151
+ if (status != ACTIVE) link->Status = status;
2245
2152
  }
2246
2153
  else if (link->Type == PUMP)
2247
2154
  {
@@ -2252,14 +2159,12 @@ void changestatus(Network *net, int j, StatusType status, double y)
2252
2159
  if (y == 0.0) status = CLOSED;
2253
2160
  }
2254
2161
  else if (status == OPEN) link->Kc = 1.0;
2255
- else if (status == CLOSED) link->Kc = 0.0;
2256
- link->InitStatus = status;
2257
- link->InitSetting = link->Kc;
2162
+ link->Status = status;
2258
2163
  }
2259
2164
  else if (link->Type >= PRV)
2260
2165
  {
2261
- if (status == ACTIVE) link->Kc = y;
2262
- link->InitStatus = status;
2263
- link->InitSetting = link->Kc;
2166
+ link->Kc = y;
2167
+ link->Status = status;
2168
+ if (status != ACTIVE) link->Kc = MISSING;
2264
2169
  }
2265
2170
  }