epyt-flow 0.14.1__py3-none-any.whl → 0.15.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. epyt_flow/VERSION +1 -1
  2. epyt_flow/__init__.py +0 -37
  3. epyt_flow/data/benchmarks/battledim.py +2 -2
  4. epyt_flow/data/benchmarks/leakdb.py +12 -9
  5. epyt_flow/gym/scenario_control_env.py +32 -33
  6. epyt_flow/simulation/events/actuator_events.py +24 -18
  7. epyt_flow/simulation/events/leakages.py +59 -57
  8. epyt_flow/simulation/events/quality_events.py +21 -30
  9. epyt_flow/simulation/events/system_event.py +3 -3
  10. epyt_flow/simulation/scada/complex_control.py +14 -12
  11. epyt_flow/simulation/scada/custom_control.py +22 -21
  12. epyt_flow/simulation/scada/scada_data.py +108 -105
  13. epyt_flow/simulation/scada/simple_control.py +38 -31
  14. epyt_flow/simulation/scenario_simulator.py +367 -395
  15. epyt_flow/simulation/sensor_config.py +31 -32
  16. epyt_flow/topology.py +11 -10
  17. epyt_flow/uncertainty/model_uncertainty.py +146 -122
  18. {epyt_flow-0.14.1.dist-info → epyt_flow-0.15.0b1.dist-info}/METADATA +12 -18
  19. epyt_flow-0.15.0b1.dist-info/RECORD +65 -0
  20. epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS +0 -60
  21. epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +0 -21
  22. epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +0 -151
  23. epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +0 -5930
  24. epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +0 -961
  25. epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +0 -79
  26. epyt_flow/EPANET/EPANET/SRC_engines/flowbalance.c +0 -186
  27. epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +0 -219
  28. epyt_flow/EPANET/EPANET/SRC_engines/genmmd.c +0 -1000
  29. epyt_flow/EPANET/EPANET/SRC_engines/hash.c +0 -177
  30. epyt_flow/EPANET/EPANET/SRC_engines/hash.h +0 -28
  31. epyt_flow/EPANET/EPANET/SRC_engines/hydcoeffs.c +0 -1303
  32. epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +0 -1172
  33. epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +0 -781
  34. epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +0 -442
  35. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +0 -464
  36. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +0 -1960
  37. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +0 -518
  38. epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +0 -884
  39. epyt_flow/EPANET/EPANET/SRC_engines/input1.c +0 -672
  40. epyt_flow/EPANET/EPANET/SRC_engines/input2.c +0 -735
  41. epyt_flow/EPANET/EPANET/SRC_engines/input3.c +0 -2265
  42. epyt_flow/EPANET/EPANET/SRC_engines/leakage.c +0 -527
  43. epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +0 -146
  44. epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +0 -24
  45. epyt_flow/EPANET/EPANET/SRC_engines/output.c +0 -853
  46. epyt_flow/EPANET/EPANET/SRC_engines/project.c +0 -1691
  47. epyt_flow/EPANET/EPANET/SRC_engines/quality.c +0 -695
  48. epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +0 -800
  49. epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +0 -696
  50. epyt_flow/EPANET/EPANET/SRC_engines/report.c +0 -1557
  51. epyt_flow/EPANET/EPANET/SRC_engines/rules.c +0 -1500
  52. epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +0 -871
  53. epyt_flow/EPANET/EPANET/SRC_engines/text.h +0 -508
  54. epyt_flow/EPANET/EPANET/SRC_engines/types.h +0 -928
  55. epyt_flow/EPANET/EPANET/SRC_engines/util/cstr_helper.c +0 -59
  56. epyt_flow/EPANET/EPANET/SRC_engines/util/cstr_helper.h +0 -38
  57. epyt_flow/EPANET/EPANET/SRC_engines/util/errormanager.c +0 -92
  58. epyt_flow/EPANET/EPANET/SRC_engines/util/errormanager.h +0 -39
  59. epyt_flow/EPANET/EPANET/SRC_engines/util/filemanager.c +0 -212
  60. epyt_flow/EPANET/EPANET/SRC_engines/util/filemanager.h +0 -81
  61. epyt_flow/EPANET/EPANET/SRC_engines/validate.c +0 -408
  62. epyt_flow/EPANET/EPANET-MSX/MSX_Updates.txt +0 -53
  63. epyt_flow/EPANET/EPANET-MSX/Src/dispersion.h +0 -27
  64. epyt_flow/EPANET/EPANET-MSX/Src/hash.c +0 -107
  65. epyt_flow/EPANET/EPANET-MSX/Src/hash.h +0 -28
  66. epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx.h +0 -102
  67. epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx_export.h +0 -42
  68. epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.c +0 -937
  69. epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.h +0 -39
  70. epyt_flow/EPANET/EPANET-MSX/Src/mempool.c +0 -204
  71. epyt_flow/EPANET/EPANET-MSX/Src/mempool.h +0 -24
  72. epyt_flow/EPANET/EPANET-MSX/Src/msxchem.c +0 -1285
  73. epyt_flow/EPANET/EPANET-MSX/Src/msxcompiler.c +0 -368
  74. epyt_flow/EPANET/EPANET-MSX/Src/msxdict.h +0 -42
  75. epyt_flow/EPANET/EPANET-MSX/Src/msxdispersion.c +0 -586
  76. epyt_flow/EPANET/EPANET-MSX/Src/msxerr.c +0 -116
  77. epyt_flow/EPANET/EPANET-MSX/Src/msxfile.c +0 -260
  78. epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.c +0 -175
  79. epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.h +0 -35
  80. epyt_flow/EPANET/EPANET-MSX/Src/msxinp.c +0 -1504
  81. epyt_flow/EPANET/EPANET-MSX/Src/msxout.c +0 -401
  82. epyt_flow/EPANET/EPANET-MSX/Src/msxproj.c +0 -791
  83. epyt_flow/EPANET/EPANET-MSX/Src/msxqual.c +0 -2010
  84. epyt_flow/EPANET/EPANET-MSX/Src/msxrpt.c +0 -400
  85. epyt_flow/EPANET/EPANET-MSX/Src/msxtank.c +0 -422
  86. epyt_flow/EPANET/EPANET-MSX/Src/msxtoolkit.c +0 -1164
  87. epyt_flow/EPANET/EPANET-MSX/Src/msxtypes.h +0 -551
  88. epyt_flow/EPANET/EPANET-MSX/Src/msxutils.c +0 -524
  89. epyt_flow/EPANET/EPANET-MSX/Src/msxutils.h +0 -56
  90. epyt_flow/EPANET/EPANET-MSX/Src/newton.c +0 -158
  91. epyt_flow/EPANET/EPANET-MSX/Src/newton.h +0 -34
  92. epyt_flow/EPANET/EPANET-MSX/Src/rk5.c +0 -287
  93. epyt_flow/EPANET/EPANET-MSX/Src/rk5.h +0 -39
  94. epyt_flow/EPANET/EPANET-MSX/Src/ros2.c +0 -293
  95. epyt_flow/EPANET/EPANET-MSX/Src/ros2.h +0 -35
  96. epyt_flow/EPANET/EPANET-MSX/Src/smatrix.c +0 -816
  97. epyt_flow/EPANET/EPANET-MSX/Src/smatrix.h +0 -29
  98. epyt_flow/EPANET/EPANET-MSX/readme.txt +0 -14
  99. epyt_flow/EPANET/compile_linux.sh +0 -4
  100. epyt_flow/EPANET/compile_macos.sh +0 -4
  101. epyt_flow/simulation/backend/__init__.py +0 -1
  102. epyt_flow/simulation/backend/my_epyt.py +0 -1101
  103. epyt_flow-0.14.1.dist-info/RECORD +0 -148
  104. {epyt_flow-0.14.1.dist-info → epyt_flow-0.15.0b1.dist-info}/WHEEL +0 -0
  105. {epyt_flow-0.14.1.dist-info → epyt_flow-0.15.0b1.dist-info}/licenses/LICENSE +0 -0
  106. {epyt_flow-0.14.1.dist-info → epyt_flow-0.15.0b1.dist-info}/top_level.txt +0 -0
@@ -1,1172 +0,0 @@
1
- /*
2
- ******************************************************************************
3
- Project: OWA EPANET
4
- Version: 2.3
5
- Module: hydraul.c
6
- Description: implements EPANET's hydraulic engine
7
- Authors: see AUTHORS
8
- Copyright: see AUTHORS
9
- License: see LICENSE
10
- Last Updated: 04/19/2025
11
- ******************************************************************************
12
- */
13
-
14
- #include <stdlib.h>
15
- #include <stdio.h>
16
- #include <string.h>
17
- #include <math.h>
18
-
19
- #include "types.h"
20
- #include "funcs.h"
21
- #include "text.h"
22
-
23
- const double QZERO = 1.e-6; // Equivalent to zero flow in cfs
24
-
25
- // Imported functions
26
- extern int validateproject(Project *);
27
- extern int createsparse(Project *);
28
- extern void freesparse(Project *);
29
- extern int hydsolve(Project *, int *, double *);
30
-
31
- // Local functions
32
- int allocmatrix(Project *);
33
- void freematrix(Project *);
34
- void initlinkflow(Project *, int, char, double);
35
- void demands(Project *);
36
- int controls(Project *);
37
- long timestep(Project *);
38
- void ruletimestep(Project *, long *);
39
- void addenergy(Project *, long);
40
- void tanklevels(Project *, long);
41
- void resetpumpflow(Project *, int);
42
- void getallpumpsenergy(Project *);
43
-
44
- int openhyd(Project *pr)
45
- /*
46
- *--------------------------------------------------------------
47
- * Input: none
48
- * Output: returns error code
49
- * Purpose: opens hydraulics solver system
50
- *--------------------------------------------------------------
51
- */
52
- {
53
- int i;
54
- int errcode = 0;
55
- Slink *link;
56
-
57
- // Check for valid project data (see VALIDATE.C)
58
- errcode = validateproject(pr);
59
- if (errcode > 0) return errcode;
60
-
61
- // Allocate memory for sparse matrix structures (see SMATRIX.C)
62
- ERRCODE(createsparse(pr));
63
-
64
- // Allocate memory for hydraulic variables
65
- ERRCODE(allocmatrix(pr));
66
-
67
- // Check for unconnected nodes
68
- ERRCODE(unlinked(pr));
69
-
70
- // Initialize link flows
71
- if (!errcode) for (i = 1; i <= pr->network.Nlinks; i++)
72
- {
73
- link = &pr->network.Link[i];
74
- initlinkflow(pr, i, link->InitStatus, link->Kc);
75
- }
76
- else closehyd(pr);
77
- return errcode;
78
- }
79
-
80
- void inithyd(Project *pr, int initflag)
81
- /*
82
- **--------------------------------------------------------------
83
- ** Input: initflag > 0 if link flows should be re-initialized
84
- ** = 0 if not
85
- ** Output: none
86
- ** Purpose: initializes hydraulics solver system
87
- **--------------------------------------------------------------
88
- */
89
- {
90
- Network *net = &pr->network;
91
- Hydraul *hyd = &pr->hydraul;
92
- Outfile *out = &pr->outfile;
93
- Times *time = &pr->times;
94
-
95
- int i;
96
- Stank *tank;
97
- Slink *link;
98
- Spump *pump;
99
-
100
- // Initialize tanks
101
- for (i = 1; i <= net->Ntanks; i++)
102
- {
103
- tank = &net->Tank[i];
104
- tank->V = tank->V0;
105
- hyd->NodeHead[tank->Node] = tank->H0;
106
- hyd->NodeDemand[tank->Node] = 0.0;
107
- hyd->OldStatus[net->Nlinks+i] = TEMPCLOSED;
108
- }
109
-
110
- // Initialize node outflows
111
- memset(hyd->DemandFlow,0,(net->Nnodes+1)*sizeof(double));
112
- memset(hyd->EmitterFlow,0,(net->Nnodes+1)*sizeof(double));
113
- memset(hyd->LeakageFlow,0,(net->Nnodes+1)*sizeof(double));
114
- for (i = 1; i <= net->Nnodes; i++)
115
- {
116
- net->Node[i].ResultIndex = i;
117
- if (net->Node[i].Ke > 0.0) hyd->EmitterFlow[i] = 1.0;
118
- }
119
-
120
- // Initialize links
121
- for (i = 1; i <= net->Nlinks; i++)
122
- {
123
- link = &net->Link[i];
124
- link->ResultIndex = i;
125
-
126
- // Initialize status and setting
127
- hyd->LinkStatus[i] = link->InitStatus;
128
- hyd->LinkSetting[i] = link->InitSetting;
129
-
130
- // Setting of non-ACTIVE FCV, PRV, PSV valves is "MISSING"
131
- switch (link->Type)
132
- {
133
- case FCV:
134
- case PRV:
135
- case PSV:
136
- if (link->InitStatus != ACTIVE)
137
- {
138
- link->Kc = MISSING;
139
- hyd->LinkSetting[i] = MISSING;
140
- }
141
- }
142
-
143
- // Compute flow resistance
144
- resistcoeff(pr, i);
145
-
146
- // Start active control valves in ACTIVE position
147
- if (
148
- (link->Type == PRV || link->Type == PSV
149
- || link->Type == FCV) && (link->Kc != MISSING)
150
- ) hyd->LinkStatus[i] = ACTIVE;
151
-
152
- // Initialize flows if necessary
153
- if (hyd->LinkStatus[i] <= CLOSED)
154
- {
155
- hyd->LinkFlow[i] = QZERO;
156
- }
157
- else if (ABS(hyd->LinkFlow[i]) <= QZERO || initflag > 0)
158
- {
159
- initlinkflow(pr, i, hyd->LinkStatus[i], hyd->LinkSetting[i]);
160
- }
161
-
162
- // Save initial status
163
- hyd->OldStatus[i] = hyd->LinkStatus[i];
164
- }
165
-
166
- // Initialize pump energy usage
167
- for (i = 1; i <= net->Npumps; i++)
168
- {
169
- pump = &net->Pump[i];
170
- pump->Energy.Efficiency = 0.0;
171
- pump->Energy.TimeOnLine = 0.0;
172
- pump->Energy.KwHrs = 0.0;
173
- pump->Energy.KwHrsPerFlow = 0.0;
174
- pump->Energy.MaxKwatts = 0.0;
175
- pump->Energy.TotalCost = 0.0;
176
- pump->Energy.CurrentPower = 0.0;
177
- pump->Energy.CurrentEffic = 0.0;
178
- }
179
-
180
- // Initialize flow balance
181
- startflowbalance(pr);
182
-
183
- // Re-position hydraulics file
184
- if (pr->outfile.Saveflag)
185
- {
186
- fseek(out->HydFile,out->HydOffset,SEEK_SET);
187
- }
188
-
189
- // Initialize current time
190
- hyd->Haltflag = 0;
191
- time->Htime = 0;
192
- time->Hydstep = 0;
193
- time->Rtime = time->Rstep;
194
- }
195
-
196
-
197
- int runhyd(Project *pr, long *t)
198
- /*
199
- **--------------------------------------------------------------
200
- ** Input: none
201
- ** Output: t = pointer to current time (in seconds)
202
- ** Returns: error code
203
- ** Purpose: solves network hydraulics in a single time period
204
- **--------------------------------------------------------------
205
- */
206
- {
207
- Hydraul *hyd = &pr->hydraul;
208
- Times *time = &pr->times;
209
- Report *rpt = &pr->report;
210
-
211
- int iter; // Iteration count
212
- int errcode; // Error code
213
- double relerr; // Solution accuracy
214
-
215
- // Find new demands & control actions
216
- *t = time->Htime;
217
- demands(pr);
218
- controls(pr);
219
-
220
- // Solve network hydraulic equations
221
- errcode = hydsolve(pr,&iter,&relerr);
222
- if (!errcode)
223
- {
224
- // Report new status & save results
225
- if (rpt->Statflag) writehydstat(pr,iter,relerr);
226
-
227
- // If system unbalanced and no extra trials
228
- // allowed, then activate the Haltflag
229
- if (relerr > hyd->Hacc && hyd->ExtraIter == -1)
230
- {
231
- hyd->Haltflag = 1;
232
- }
233
-
234
- // Report any warning conditions
235
- if (!errcode) errcode = writehydwarn(pr,iter,relerr);
236
- }
237
- return errcode;
238
- }
239
-
240
- int nexthyd(Project *pr, long *tstep)
241
- /*
242
- **--------------------------------------------------------------
243
- ** Input: none
244
- ** Output: tstep = pointer to time step (in seconds)
245
- ** Returns: error code
246
- ** Purpose: finds length of next time step & updates tank
247
- ** levels and rule-based contol actions
248
- **--------------------------------------------------------------
249
- */
250
- {
251
- Hydraul *hyd = &pr->hydraul;
252
- Times *time = &pr->times;
253
-
254
- long hydstep; // Actual time step
255
- int errcode = 0; // Error code
256
-
257
- // Compute current power and efficiency of all pumps
258
- getallpumpsenergy(pr);
259
-
260
- // Save current results to hydraulics file and
261
- // force end of simulation if Haltflag is active
262
- if (pr->outfile.Saveflag) errcode = savehyd(pr, &time->Htime);
263
- if (hyd->Haltflag) time->Htime = time->Dur;
264
-
265
- // Compute next time step & update tank levels
266
- *tstep = 0;
267
- hydstep = 0;
268
- if (time->Htime < time->Dur) hydstep = timestep(pr);
269
- if (pr->outfile.Saveflag) errcode = savehydstep(pr,&hydstep);
270
-
271
- // Accumulate pumping energy
272
- if (time->Dur == 0) addenergy(pr,0);
273
- else if (time->Htime < time->Dur) addenergy(pr,hydstep);
274
-
275
- // Update flow balance
276
- updateflowbalance(pr, hydstep);
277
-
278
- // More time remains - update current time
279
- if (time->Htime < time->Dur)
280
- {
281
- time->Htime += hydstep;
282
- if (!pr->quality.OpenQflag)
283
- {
284
- if (time->Htime >= time->Rtime) time->Rtime += time->Rstep;
285
- }
286
- }
287
-
288
- // No more time remains - force completion of analysis
289
- else
290
- {
291
- endflowbalance(pr);
292
- if (pr->report.Statflag) writeflowbalance(pr);
293
- time->Htime++;
294
- if (pr->quality.OpenQflag) time->Qtime++;
295
- }
296
- *tstep = hydstep;
297
- return errcode;
298
- }
299
-
300
-
301
- void closehyd(Project *pr)
302
- /*
303
- **--------------------------------------------------------------
304
- ** Input: none
305
- ** Output: returns error code
306
- ** Purpose: closes hydraulics solver system
307
- **--------------------------------------------------------------
308
- */
309
- {
310
- freesparse(pr);
311
- freematrix(pr);
312
- freeadjlists(&pr->network);
313
- }
314
-
315
-
316
- int allocmatrix(Project *pr)
317
- /*
318
- **--------------------------------------------------------------
319
- ** Input: none
320
- ** Output: returns error code
321
- ** Purpose: allocates memory used for solution matrix coeffs.
322
- **--------------------------------------------------------------
323
- */
324
- {
325
- Network *net = &pr->network;
326
- Hydraul *hyd = &pr->hydraul;
327
-
328
- int errcode = 0;
329
-
330
- hyd->P = (double *) calloc(net->Nlinks+1,sizeof(double));
331
- hyd->Y = (double *) calloc(net->Nlinks+1,sizeof(double));
332
- hyd->Xflow = (double *) calloc(MAX((net->Nnodes+1), (net->Nlinks+1)),
333
- sizeof(double));
334
- hyd->OldStatus = (StatusType *) calloc(net->Nlinks+net->Ntanks+1,
335
- sizeof(StatusType));
336
- ERRCODE(MEMCHECK(hyd->P));
337
- ERRCODE(MEMCHECK(hyd->Y));
338
- ERRCODE(MEMCHECK(hyd->Xflow));
339
- ERRCODE(MEMCHECK(hyd->OldStatus));
340
- return errcode;
341
- }
342
-
343
-
344
- void freematrix(Project *pr)
345
- /*
346
- **--------------------------------------------------------------
347
- ** Input: none
348
- ** Output: none
349
- ** Purpose: frees memory used for solution matrix coeffs.
350
- **--------------------------------------------------------------
351
- */
352
- {
353
- Hydraul *hyd = &pr->hydraul;
354
-
355
- free(hyd->P);
356
- free(hyd->Y);
357
- free(hyd->Xflow);
358
- free(hyd->OldStatus);
359
- }
360
-
361
-
362
- void initlinkflow(Project *pr, int i, char s, double k)
363
- /*
364
- **--------------------------------------------------------------------
365
- ** Input: i = link index
366
- ** s = link status
367
- ** k = link setting (i.e., pump speed)
368
- ** Output: none
369
- ** Purpose: sets initial flow in link to QZERO if link is closed,
370
- ** to design flow for a pump, or to flow at velocity of
371
- ** 1 fps for other links.
372
- **--------------------------------------------------------------------
373
- */
374
- {
375
- Hydraul *hyd = &pr->hydraul;
376
- Network *n = &pr->network;
377
-
378
- Slink *link = &n->Link[i];
379
-
380
- if (s == CLOSED)
381
- {
382
- hyd->LinkFlow[i] = QZERO;
383
- }
384
- else if (link->Type == PUMP)
385
- {
386
- hyd->LinkFlow[i] = k * n->Pump[findpump(n,i)].Q0;
387
- }
388
- else
389
- {
390
- hyd->LinkFlow[i] = PI * SQR(link->Diam)/4.0;
391
- }
392
- }
393
-
394
-
395
- void setlinkstatus(Project *pr, int index, char value, StatusType *s, double *k)
396
- /*----------------------------------------------------------------
397
- ** Input: index = link index
398
- ** value = 0 (CLOSED) or 1 (OPEN)
399
- ** s = pointer to link status
400
- ** k = pointer to link setting
401
- ** Output: none
402
- ** Purpose: sets link status to OPEN or CLOSED
403
- **----------------------------------------------------------------
404
- */
405
- {
406
- Network *net = &pr->network;
407
-
408
- Slink *link = &net->Link[index];
409
- LinkType t = link->Type;
410
-
411
- // Status set to open
412
- if (value == 1)
413
- {
414
- // Adjust link setting for pumps & valves
415
- if (t == PUMP)
416
- {
417
- *k = 1.0;
418
- // Check if a re-opened pump needs its flow reset
419
- if (*s == CLOSED) resetpumpflow(pr, index);
420
- }
421
- if (t > PUMP && t != GPV) *k = MISSING;
422
- *s = OPEN;
423
- }
424
-
425
- // Status set to closed
426
- else if (value == 0)
427
- {
428
- // Adjust link setting for pumps & valves
429
- if (t == PUMP) *k = 0.0;
430
- if (t > PUMP && t != GPV) *k = MISSING;
431
- *s = CLOSED;
432
- }
433
- }
434
-
435
-
436
- void setlinksetting(Project *pr, int index, double value, StatusType *s,
437
- double *k)
438
- /*----------------------------------------------------------------
439
- ** Input: index = link index
440
- ** value = pump speed or valve setting
441
- ** s = pointer to link status
442
- ** k = pointer to link setting
443
- ** Output: none
444
- ** Purpose: sets pump speed or valve setting, adjusting link
445
- ** status and flow when necessary
446
- **----------------------------------------------------------------
447
- */
448
- {
449
- Network *net = &pr->network;
450
-
451
- Slink *link = &net->Link[index];
452
- LinkType t = link->Type;
453
-
454
- // For a pump, status is OPEN if speed > 0, CLOSED otherwise
455
- if (t == PUMP)
456
- {
457
- *k = value;
458
- if (value > 0 && *s <= CLOSED)
459
- {
460
- // Check if a re-opened pump needs its flow reset
461
- resetpumpflow(pr, index);
462
- *s = OPEN;
463
- }
464
- if (value == 0 && *s > CLOSED) *s = CLOSED;
465
- }
466
-
467
- // For FCV, activate it
468
- else if (t == FCV)
469
- {
470
- *k = value;
471
- *s = ACTIVE;
472
- }
473
-
474
- // Open closed control valve with fixed status (setting = MISSING)
475
- else
476
- {
477
- if (*k == MISSING && *s <= CLOSED) *s = OPEN;
478
- if (t == PCV) link->R = pcvlosscoeff(pr, index, link->Kc);
479
- *k = value;
480
- }
481
- }
482
-
483
-
484
- void demands(Project *pr)
485
- /*
486
- **--------------------------------------------------------------------
487
- ** Input: none
488
- ** Output: none
489
- ** Purpose: computes demands at nodes during current time period
490
- **--------------------------------------------------------------------
491
- */
492
- {
493
- Network *net = &pr->network;
494
- Hydraul *hyd = &pr->hydraul;
495
- Times *time = &pr->times;
496
-
497
- int i ,j, n;
498
- long k, p;
499
- double djunc, sum;
500
- Pdemand demand;
501
-
502
- // Determine total elapsed number of pattern periods
503
- p = (time->Htime + time->Pstart) / time->Pstep;
504
-
505
- // Update demand at each node according to its assigned pattern
506
- hyd->Dsystem = 0.0; // System-wide demand
507
- for (i = 1; i <= net->Njuncs; i++)
508
- {
509
- sum = 0.0;
510
- for (demand = net->Node[i].D; demand != NULL; demand = demand->next)
511
- {
512
- // pattern period (k) = (elapsed periods) modulus (periods per pattern)
513
- j = demand->Pat;
514
- if (j == 0)
515
- j = hyd->DefPat;
516
- k = p % (long)net->Pattern[j].Length;
517
- djunc = (demand->Base) * net->Pattern[j].F[k] * hyd->Dmult;
518
- if (djunc > 0.0) hyd->Dsystem += djunc;
519
- sum += djunc;
520
- }
521
- hyd->FullDemand[i] = sum;
522
-
523
- // Initialize pressure dependent demand
524
- hyd->DemandFlow[i] = sum;
525
- }
526
-
527
- // Update head at fixed grade nodes with time patterns
528
- for (n = 1; n <= net->Ntanks; n++)
529
- {
530
- Stank *tank = &net->Tank[n];
531
- if (tank->A == 0.0)
532
- {
533
- j = tank->Pat;
534
- if (j > 0)
535
- {
536
- k = p % (long) net->Pattern[j].Length;
537
- i = tank->Node;
538
- hyd->NodeHead[i] = net->Node[i].El * net->Pattern[j].F[k];
539
- }
540
- }
541
- }
542
-
543
- // Update status of pumps with utilization patterns
544
- for (n = 1; n <= net->Npumps; n++)
545
- {
546
- Spump *pump = &net->Pump[n];
547
- j = pump->Upat;
548
- if (j > 0)
549
- {
550
- i = pump->Link;
551
- k = p % (long) net->Pattern[j].Length;
552
- setlinksetting(pr, i, net->Pattern[j].F[k], &hyd->LinkStatus[i],
553
- &hyd->LinkSetting[i]);
554
- }
555
- }
556
- }
557
-
558
-
559
- int controls(Project *pr)
560
- /*
561
- **---------------------------------------------------------------------
562
- ** Input: none
563
- ** Output: number of links whose setting changes
564
- ** Purpose: implements simple controls based on time or tank levels
565
- **---------------------------------------------------------------------
566
- */
567
- {
568
- Network *net = &pr->network;
569
- Hydraul *hyd = &pr->hydraul;
570
- Times *time = &pr->times;
571
-
572
- int i, k, n, reset, setsum;
573
- double h, vplus;
574
- double v1, v2;
575
- double k1, k2;
576
- char s1, s2;
577
- Slink *link;
578
- Scontrol *control;
579
-
580
- // Examine each control statement
581
- setsum = 0;
582
- for (i=1; i <= net->Ncontrols; i++)
583
- {
584
- // Make sure that link is defined
585
- control = &net->Control[i];
586
- if (!control->isEnabled)
587
- {
588
- continue;
589
- }
590
- reset = 0;
591
- if ( (k = control->Link) <= 0) continue;
592
- link = &net->Link[k];
593
-
594
- // Link is controlled by tank level
595
- if ((n = control->Node) > 0 && n > net->Njuncs)
596
- {
597
- h = hyd->NodeHead[n];
598
- vplus = ABS(hyd->NodeDemand[n]);
599
- v1 = tankvolume(pr,n - net->Njuncs,h);
600
- v2 = tankvolume(pr,n - net->Njuncs, control->Grade);
601
- if (control->Type == LOWLEVEL && v1 <= v2 + vplus) reset = 1;
602
- if (control->Type == HILEVEL && v1 >= v2 - vplus) reset = 1;
603
- }
604
-
605
- // Link is time-controlled
606
- if (control->Type == TIMER)
607
- {
608
- if (control->Time == time->Htime) reset = 1;
609
- }
610
-
611
- //* Link is time-of-day controlled
612
- if (control->Type == TIMEOFDAY)
613
- {
614
- if ((time->Htime + time->Tstart) % SECperDAY == control->Time)
615
- {
616
- reset = 1;
617
- }
618
- }
619
-
620
- // Update link status & pump speed or valve setting
621
- if (reset == 1)
622
- {
623
- if (hyd->LinkStatus[k] <= CLOSED) s1 = CLOSED;
624
- else s1 = OPEN;
625
- s2 = control->Status;
626
- k1 = hyd->LinkSetting[k];
627
- k2 = k1;
628
- if (link->Type > PIPE) k2 = control->Setting;
629
-
630
- // Check if a re-opened pump needs its flow reset
631
- if (link->Type == PUMP && s1 == CLOSED && s2 == OPEN)
632
- resetpumpflow(pr, k);
633
-
634
- if (s1 != s2 || k1 != k2)
635
- {
636
- hyd->LinkStatus[k] = s2;
637
- hyd->LinkSetting[k] = k2;
638
- if (link->Type == PCV) link->R = pcvlosscoeff(pr, k, k2);
639
- if (pr->report.Statflag) writecontrolaction(pr,k,i);
640
- setsum++;
641
- }
642
- }
643
- }
644
- return setsum;
645
- }
646
-
647
-
648
- long timestep(Project *pr)
649
- /*
650
- **----------------------------------------------------------------
651
- ** Input: none
652
- ** Output: returns time step until next change in hydraulics
653
- ** Purpose: computes time step to advance hydraulic simulation
654
- **----------------------------------------------------------------
655
- */
656
- {
657
- Network *net = &pr->network;
658
- Times *time = &pr->times;
659
-
660
- long n, t, tstep;
661
-
662
- // Normal time step is hydraulic time step
663
- tstep = time->Hstep;
664
-
665
- // Revise time step based on time until next demand period
666
- // (n = next pattern period, t = time till next period)
667
- n = ((time->Htime + time->Pstart) / time->Pstep) + 1;
668
- t = n * time->Pstep - time->Htime;
669
- if (t > 0 && t < tstep) tstep = t;
670
-
671
- // Revise time step based on time until next reporting period
672
- t = time->Rtime - time->Htime;
673
- if (t > 0 && t < tstep) tstep = t;
674
-
675
- // Revise time step based on smallest time to fill or drain a tank
676
- tanktimestep(pr, &tstep);
677
-
678
- // Revise time step based on smallest time to activate a control
679
- controltimestep(pr, &tstep);
680
-
681
- // Evaluate rule-based controls (which will also update tank levels)
682
- if (net->Nrules > 0) ruletimestep(pr, &tstep);
683
- else tanklevels(pr, tstep);
684
- return tstep;
685
- }
686
-
687
-
688
- int tanktimestep(Project *pr, long *tstep)
689
- /*
690
- **-----------------------------------------------------------------
691
- ** Input: *tstep = current time step
692
- ** Output: *tstep = modified current time step
693
- ** Purpose: revises time step based on shortest time to fill or
694
- ** drain a tank
695
- **-----------------------------------------------------------------
696
- */
697
- {
698
- Network *net = &pr->network;
699
- Hydraul *hyd = &pr->hydraul;
700
-
701
- int i, n, tankIdx = 0;
702
- double h, q, v, xt;
703
- long t;
704
- Stank *tank;
705
-
706
- // Examine each tank
707
- for (i = 1; i <= net->Ntanks; i++)
708
- {
709
- // Skip reservoirs
710
- tank = &net->Tank[i];
711
- if (tank->A == 0.0) continue;
712
-
713
- // Get current tank grade (h) & inflow (q)
714
- n = tank->Node;
715
- h = hyd->NodeHead[n];
716
- q = hyd->NodeDemand[n];
717
- if (ABS(q) <= QZERO) continue;
718
-
719
- // Find volume to fill/drain tank
720
- if (q > 0.0 && h < tank->Hmax) v = tank->Vmax - tank->V;
721
- else if (q < 0.0 && h > tank->Hmin) v = tank->Vmin - tank->V;
722
- else continue;
723
-
724
- // Find time to fill/drain tank
725
- xt = v / q;
726
- if (ABS(xt) > *tstep + 1) continue;
727
- t = (long)ROUND(xt);
728
- if (t > 0 && t < *tstep)
729
- {
730
- *tstep = t;
731
- tankIdx = n;
732
- }
733
- }
734
- return tankIdx;
735
- }
736
-
737
-
738
- int controltimestep(Project *pr, long *tstep)
739
- /*
740
- **------------------------------------------------------------------
741
- ** Input: *tstep = current time step
742
- ** Output: *tstep = modified current time step
743
- ** Purpose: revises time step based on shortest time to activate
744
- ** a simple control
745
- **------------------------------------------------------------------
746
- */
747
- {
748
- Network *net = &pr->network;
749
- Hydraul *hyd = &pr->hydraul;
750
-
751
- int i, j, k, n, controlIndex = 0;
752
- double h, q, v;
753
- long t, t1, t2;
754
- Slink *link;
755
- Scontrol *control;
756
-
757
- // Examine each control
758
- for (i = 1; i <= net->Ncontrols; i++)
759
- {
760
- t = 0;
761
- control = &net->Control[i];
762
- if (!control->isEnabled)
763
- {
764
- continue;
765
- }
766
- // Control depends on a tank level
767
- if ( (n = control->Node) > 0)
768
- {
769
- // Skip node if not a tank or reservoir
770
- if ((j = n - net->Njuncs) <= 0) continue;
771
-
772
- // Find current head and flow into tank
773
- h = hyd->NodeHead[n];
774
- q = hyd->NodeDemand[n];
775
- if (ABS(q) <= QZERO) continue;
776
-
777
- // Find time to reach upper or lower control level
778
- if ( (h < control->Grade && control->Type == HILEVEL && q > 0.0)
779
- || (h > control->Grade && control->Type == LOWLEVEL && q < 0.0) )
780
- {
781
- v = tankvolume(pr, j, control->Grade) - net->Tank[j].V;
782
- t = (long)ROUND(v/q);
783
- }
784
- }
785
-
786
- // Control is based on elapsed time
787
- if (control->Type == TIMER)
788
- {
789
- if (control->Time > pr->times.Htime)
790
- {
791
- t = control->Time - pr->times.Htime;
792
- }
793
- }
794
-
795
- // Control is based on time of day
796
- if (control->Type == TIMEOFDAY)
797
- {
798
- t1 = (pr->times.Htime + pr->times.Tstart) % SECperDAY;
799
- t2 = control->Time;
800
- if (t2 >= t1) t = t2 - t1;
801
- else t = SECperDAY - t1 + t2;
802
- }
803
-
804
- // Revise the current estimated next time step
805
- if (t > 0 && t < *tstep)
806
- {
807
- // Check if rule actually changes link status or setting
808
- k = control->Link;
809
- link = &net->Link[k];
810
- if ( (link->Type > PIPE && hyd->LinkSetting[k] != control->Setting)
811
- || (hyd->LinkStatus[k] != control->Status) )
812
- {
813
- *tstep = t;
814
- controlIndex = i;
815
- }
816
- }
817
- }
818
- return controlIndex;
819
- }
820
-
821
-
822
- void ruletimestep(Project *pr, long *tstep)
823
- /*
824
- **--------------------------------------------------------------
825
- ** Input: *tstep = current time step (sec)
826
- ** Output: *tstep = modified time step
827
- ** Purpose: updates next time step by checking if any rules
828
- ** will fire before then; also updates tank levels.
829
- **--------------------------------------------------------------
830
- */
831
- {
832
- Network *net = &pr->network;
833
- Times *time = &pr->times;
834
-
835
- long tnow, // Start of time interval for rule evaluation
836
- tmax, // End of time interval for rule evaluation
837
- dt, // Normal time increment for rule evaluation
838
- dt1; // Actual time increment for rule evaluation
839
-
840
- // Find interval of time for rule evaluation
841
- tnow = time->Htime;
842
- tmax = tnow + *tstep;
843
-
844
- // If no rules, then time increment equals current time step
845
- if (net->Nrules == 0)
846
- {
847
- dt = *tstep;
848
- dt1 = dt;
849
- }
850
-
851
- // Otherwise, time increment equals rule evaluation time step and
852
- // first actual increment equals time until next even multiple of
853
- // Rulestep occurs.
854
- else
855
- {
856
- dt = time->Rulestep;
857
- dt1 = time->Rulestep - (tnow % time->Rulestep);
858
- }
859
-
860
- // Make sure time increment is no larger than current time step
861
- dt = MIN(dt, *tstep);
862
- dt1 = MIN(dt1, *tstep);
863
- if (dt1 == 0) dt1 = dt;
864
-
865
- // Step through time, updating tank levels, until either
866
- // a rule fires or we reach the end of evaluation period.
867
- //
868
- // Note: we are updating the global simulation time (Htime)
869
- // here because it is used by functions in RULES.C
870
- // to evaluate rules when checkrules() is called.
871
- // It is restored to its original value after the
872
- // rule evaluation process is completed (see below).
873
- // Also note that dt1 will equal dt after the first
874
- // time increment is taken.
875
- //
876
- do
877
- {
878
- time->Htime += dt1; // Update simulation clock
879
- tanklevels(pr, dt1); // Find new tank levels
880
- if (checkrules(pr, dt1)) break; // Stop if any rule fires
881
- dt = MIN(dt, tmax - time->Htime); // Update time increment
882
- dt1 = dt; // Update actual increment
883
- } while (dt > 0); // Stop if no time left
884
-
885
- // Compute an updated simulation time step (*tstep)
886
- // and return simulation time to its original value
887
- *tstep = time->Htime - tnow;
888
- time->Htime = tnow;
889
- }
890
-
891
-
892
- void addenergy(Project *pr, long hstep)
893
- /*
894
- **-------------------------------------------------------------
895
- ** Input: hstep = time step (sec)
896
- ** Output: none
897
- ** Purpose: accumulates pump energy usage
898
- **-------------------------------------------------------------
899
- */
900
- {
901
- Network *net = &pr->network;
902
- Hydraul *hyd = &pr->hydraul;
903
- Times *time = &pr->times;
904
-
905
- int i, j, k;
906
- long m, n;
907
- double c0, c, // Energy cost (cost/kwh)
908
- f0, // Energy cost factor
909
- dt, // Time interval (hr)
910
- e, // Pump efficiency (fraction)
911
- q, // Pump flow (cfs)
912
- p, // Pump energy (kw)
913
- psum = 0.0; // Total energy (kw)
914
- Spump *pump;
915
-
916
- // Determine current time interval in hours
917
- if (time->Dur == 0) dt = 1.0;
918
- else if (time->Htime < time->Dur)
919
- {
920
- dt = (double) hstep / 3600.0;
921
- }
922
- else dt = 0.0;
923
- if (dt == 0.0) return;
924
- n = (time->Htime + time->Pstart) / time->Pstep;
925
-
926
- // Compute default energy cost at current time
927
- c0 = hyd->Ecost;
928
- f0 = 1.0;
929
- if (hyd->Epat > 0)
930
- {
931
- m = n % (long)net->Pattern[hyd->Epat].Length;
932
- f0 = net->Pattern[hyd->Epat].F[m];
933
- }
934
-
935
- // Examine each pump
936
- for (j = 1; j <= net->Npumps; j++)
937
- {
938
- // Skip closed pumps
939
- pump = &net->Pump[j];
940
- k = pump->Link;
941
- if (pump->Energy.CurrentEffic == 0.0) continue;
942
- q = MAX(QZERO, ABS(hyd->LinkFlow[k]));
943
-
944
- // Find pump-specific energy cost
945
- if (pump->Ecost > 0.0) c = pump->Ecost;
946
- else c = c0;
947
- if ( (i = pump->Epat) > 0)
948
- {
949
- m = n % (long)net->Pattern[i].Length;
950
- c *= net->Pattern[i].F[m];
951
- }
952
- else c *= f0;
953
-
954
- // Update pump's cumulative statistics
955
- p = pump->Energy.CurrentPower;
956
- e = pump->Energy.CurrentEffic;
957
- psum += p;
958
- pump->Energy.TimeOnLine += dt;
959
- pump->Energy.Efficiency += e * dt;
960
- pump->Energy.KwHrsPerFlow += p / q * dt;
961
- pump->Energy.KwHrs += p * dt;
962
- pump->Energy.MaxKwatts = MAX(pump->Energy.MaxKwatts, p);
963
- pump->Energy.TotalCost += c * p * dt;
964
- }
965
-
966
- // Update maximum kw value
967
- hyd->Emax = MAX(hyd->Emax, psum);
968
- }
969
-
970
-
971
- void getenergy(Project *pr, int k, double *kw, double *eff)
972
- /*
973
- **----------------------------------------------------------------
974
- ** Input: k = link index
975
- ** Output: *kw = kwatt energy used
976
- ** *eff = efficiency (pumps only)
977
- ** Purpose: computes flow energy associated with link k
978
- **----------------------------------------------------------------
979
- */
980
- {
981
- Network *net = &pr->network;
982
- Hydraul *hyd = &pr->hydraul;
983
-
984
- int i, // efficiency curve index
985
- j; // pump index
986
- double dh, // head across pump (ft)
987
- q, // flow through pump (cfs)
988
- e; // pump efficiency
989
- double q4eff; // flow at nominal pump speed of 1.0
990
- double speed; // current speed setting
991
- Scurve *curve;
992
- Slink *link = &net->Link[k];
993
-
994
- // No energy if link is closed
995
- if (hyd->LinkStatus[k] <= CLOSED)
996
- {
997
- *kw = 0.0;
998
- *eff = 0.0;
999
- return;
1000
- }
1001
-
1002
- // Determine flow and head difference
1003
- q = ABS(hyd->LinkFlow[k]);
1004
- dh = ABS(hyd->NodeHead[link->N1] - hyd->NodeHead[link->N2]);
1005
-
1006
- // For pumps, find effic. at current flow
1007
- if (link->Type == PUMP)
1008
- {
1009
- j = findpump(net, k);
1010
- e = hyd->Epump;
1011
- speed = hyd->LinkSetting[k];
1012
- if ((i = net->Pump[j].Ecurve) > 0)
1013
- {
1014
- q4eff = q / speed * pr->Ucf[FLOW];
1015
- curve = &net->Curve[i];
1016
- e = interp(curve->Npts,curve->X, curve->Y, q4eff);
1017
-
1018
- // Sarbu and Borza pump speed adjustment
1019
- e = 100.0 - ((100.0-e) * pow(1.0/speed, 0.1));
1020
- }
1021
- e = MIN(e, 100.0);
1022
- e = MAX(e, 1.0);
1023
- e /= 100.0;
1024
- }
1025
- else e = 1.0;
1026
-
1027
- // Compute energy
1028
- *kw = dh * q * hyd->SpGrav / 8.814 / e * KWperHP;
1029
- *eff = e;
1030
- }
1031
-
1032
-
1033
- void getallpumpsenergy(Project *pr)
1034
- /*
1035
- **-------------------------------------------------------------
1036
- ** Input: none
1037
- ** Output: none
1038
- ** Purpose: finds the current power and efficiency for each pump.
1039
- **-------------------------------------------------------------
1040
- */
1041
- {
1042
- int j;
1043
- Spump *pump;
1044
-
1045
- for (j = 1; j <= pr->network.Npumps; j++)
1046
- {
1047
- pump = &(pr->network.Pump[j]);
1048
- getenergy(pr, pump->Link, &(pump->Energy.CurrentPower),
1049
- &(pump->Energy.CurrentEffic));
1050
- }
1051
- }
1052
-
1053
-
1054
- void tanklevels(Project *pr, long tstep)
1055
- /*
1056
- **----------------------------------------------------------------
1057
- ** Input: tstep = current time step
1058
- ** Output: none
1059
- ** Purpose: computes new water levels in tanks after current
1060
- ** time step
1061
- **----------------------------------------------------------------
1062
- */
1063
- {
1064
- Network *net = &pr->network;
1065
- Hydraul *hyd = &pr->hydraul;
1066
-
1067
- int i, n;
1068
- double dv;
1069
-
1070
- for (i = 1; i <= net->Ntanks; i++)
1071
- {
1072
- Stank *tank = &net->Tank[i];
1073
- if (tank->A == 0.0) continue; // Skip reservoirs
1074
-
1075
- // Update the tank's volume & water elevation
1076
- n = tank->Node;
1077
- dv = hyd->NodeDemand[n] * tstep;
1078
- tank->V += dv;
1079
-
1080
- // Check if tank full/empty within next second
1081
- if (tank->V + hyd->NodeDemand[n] >= tank->Vmax)
1082
- {
1083
- tank->V = tank->Vmax;
1084
- }
1085
- else if (tank->V - hyd->NodeDemand[n] <= tank->Vmin)
1086
- {
1087
- tank->V = tank->Vmin;
1088
- }
1089
- hyd->NodeHead[n] = tankgrade(pr, i, tank->V);
1090
- }
1091
- }
1092
-
1093
-
1094
- double tankvolume(Project *pr, int i, double h)
1095
- /*
1096
- **--------------------------------------------------------------------
1097
- ** Input: i = tank index
1098
- ** h = water elevation in tank
1099
- ** Output: returns water volume in tank
1100
- ** Purpose: finds water volume in tank i corresponding to elev. h.
1101
- **--------------------------------------------------------------------
1102
- */
1103
- {
1104
- Network *net = &pr->network;
1105
-
1106
- int j;
1107
- double y, v;
1108
- Stank *tank = &net->Tank[i];
1109
- Scurve *curve;
1110
-
1111
- // Use level*area if no volume curve
1112
- j = tank->Vcurve;
1113
- if (j == 0) return(tank->Vmin + (h - tank->Hmin) * tank->A);
1114
-
1115
- // If curve exists, interpolate on h to find volume v
1116
- // remembering that volume curve is in original units.
1117
- else
1118
- {
1119
- curve = &net->Curve[j];
1120
- y = (h - net->Node[tank->Node].El) * pr->Ucf[HEAD];
1121
- v = interp(curve->Npts, curve->X, curve->Y, y) / pr->Ucf[VOLUME];
1122
- return v;
1123
- }
1124
- }
1125
-
1126
-
1127
- double tankgrade(Project *pr, int i, double v)
1128
- /*
1129
- **-------------------------------------------------------------------
1130
- ** Input: i = tank index
1131
- ** v = volume in tank
1132
- ** Output: returns water level in tank
1133
- ** Purpose: finds water level in tank i corresponding to volume v.
1134
- **-------------------------------------------------------------------
1135
- */
1136
- {
1137
- Network *net = &pr->network;
1138
-
1139
- int j;
1140
- double y, h;
1141
- Stank *tank = &net->Tank[i];
1142
-
1143
- // Use area if no volume curve
1144
- j = tank->Vcurve;
1145
- if (j == 0) return(tank->Hmin + (v - tank->Vmin) / tank->A);
1146
-
1147
- // If curve exists, interpolate on volume (originally the Y-variable
1148
- // but used here as the X-variable) to find new level above bottom.
1149
- // Remember that volume curve is stored in original units.
1150
- else
1151
- {
1152
- Scurve *curve = &net->Curve[j];
1153
- y = interp(curve->Npts, curve->Y, curve->X, v * pr->Ucf[VOLUME]);
1154
- h = net->Node[tank->Node].El + y / pr->Ucf[HEAD];
1155
- return h;
1156
- }
1157
- }
1158
-
1159
- void resetpumpflow(Project *pr, int i)
1160
- /*
1161
- **-------------------------------------------------------------------
1162
- ** Input: i = link index
1163
- ** Output: none
1164
- ** Purpose: resets flow in a constant HP pump to its initial value.
1165
- **-------------------------------------------------------------------
1166
- */
1167
- {
1168
- Network *net = &pr->network;
1169
- Spump *pump = &net->Pump[findpump(net, i)];
1170
- if (pump->Ptype == CONST_HP)
1171
- pr->hydraul.LinkFlow[i] = pump->Q0;
1172
- }