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