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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. epyt_flow/VERSION +1 -1
  2. epyt_flow/__init__.py +0 -37
  3. epyt_flow/data/benchmarks/battledim.py +2 -2
  4. epyt_flow/data/benchmarks/leakdb.py +12 -9
  5. epyt_flow/gym/scenario_control_env.py +32 -33
  6. epyt_flow/simulation/events/actuator_events.py +24 -18
  7. epyt_flow/simulation/events/leakages.py +59 -57
  8. epyt_flow/simulation/events/quality_events.py +21 -30
  9. epyt_flow/simulation/events/system_event.py +3 -3
  10. epyt_flow/simulation/scada/complex_control.py +14 -12
  11. epyt_flow/simulation/scada/custom_control.py +22 -21
  12. epyt_flow/simulation/scada/scada_data.py +107 -104
  13. epyt_flow/simulation/scada/simple_control.py +38 -31
  14. epyt_flow/simulation/scenario_simulator.py +367 -395
  15. epyt_flow/simulation/sensor_config.py +31 -32
  16. epyt_flow/topology.py +11 -10
  17. epyt_flow/uncertainty/model_uncertainty.py +146 -122
  18. epyt_flow/utils.py +0 -66
  19. epyt_flow/visualization/visualization_utils.py +2 -4
  20. {epyt_flow-0.14.2.dist-info → epyt_flow-0.15.0b1.dist-info}/METADATA +12 -18
  21. epyt_flow-0.15.0b1.dist-info/RECORD +65 -0
  22. epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS +0 -28
  23. epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +0 -21
  24. epyt_flow/EPANET/EPANET/SRC_engines/Readme_SRC_Engines.txt +0 -18
  25. epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +0 -134
  26. epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +0 -5578
  27. epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +0 -865
  28. epyt_flow/EPANET/EPANET/SRC_engines/epanet2.def +0 -131
  29. epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +0 -73
  30. epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +0 -193
  31. epyt_flow/EPANET/EPANET/SRC_engines/genmmd.c +0 -1000
  32. epyt_flow/EPANET/EPANET/SRC_engines/hash.c +0 -177
  33. epyt_flow/EPANET/EPANET/SRC_engines/hash.h +0 -28
  34. epyt_flow/EPANET/EPANET/SRC_engines/hydcoeffs.c +0 -1151
  35. epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +0 -1117
  36. epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +0 -720
  37. epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +0 -476
  38. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +0 -431
  39. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +0 -1786
  40. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +0 -468
  41. epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +0 -810
  42. epyt_flow/EPANET/EPANET/SRC_engines/input1.c +0 -707
  43. epyt_flow/EPANET/EPANET/SRC_engines/input2.c +0 -864
  44. epyt_flow/EPANET/EPANET/SRC_engines/input3.c +0 -2170
  45. epyt_flow/EPANET/EPANET/SRC_engines/main.c +0 -93
  46. epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +0 -142
  47. epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +0 -24
  48. epyt_flow/EPANET/EPANET/SRC_engines/output.c +0 -852
  49. epyt_flow/EPANET/EPANET/SRC_engines/project.c +0 -1359
  50. epyt_flow/EPANET/EPANET/SRC_engines/quality.c +0 -685
  51. epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +0 -743
  52. epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +0 -694
  53. epyt_flow/EPANET/EPANET/SRC_engines/report.c +0 -1489
  54. epyt_flow/EPANET/EPANET/SRC_engines/rules.c +0 -1362
  55. epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +0 -871
  56. epyt_flow/EPANET/EPANET/SRC_engines/text.h +0 -497
  57. epyt_flow/EPANET/EPANET/SRC_engines/types.h +0 -874
  58. epyt_flow/EPANET/EPANET-MSX/MSX_Updates.txt +0 -53
  59. epyt_flow/EPANET/EPANET-MSX/Src/dispersion.h +0 -27
  60. epyt_flow/EPANET/EPANET-MSX/Src/hash.c +0 -107
  61. epyt_flow/EPANET/EPANET-MSX/Src/hash.h +0 -28
  62. epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx.h +0 -102
  63. epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx_export.h +0 -42
  64. epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.c +0 -937
  65. epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.h +0 -39
  66. epyt_flow/EPANET/EPANET-MSX/Src/mempool.c +0 -204
  67. epyt_flow/EPANET/EPANET-MSX/Src/mempool.h +0 -24
  68. epyt_flow/EPANET/EPANET-MSX/Src/msxchem.c +0 -1285
  69. epyt_flow/EPANET/EPANET-MSX/Src/msxcompiler.c +0 -368
  70. epyt_flow/EPANET/EPANET-MSX/Src/msxdict.h +0 -42
  71. epyt_flow/EPANET/EPANET-MSX/Src/msxdispersion.c +0 -586
  72. epyt_flow/EPANET/EPANET-MSX/Src/msxerr.c +0 -116
  73. epyt_flow/EPANET/EPANET-MSX/Src/msxfile.c +0 -260
  74. epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.c +0 -175
  75. epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.h +0 -35
  76. epyt_flow/EPANET/EPANET-MSX/Src/msxinp.c +0 -1504
  77. epyt_flow/EPANET/EPANET-MSX/Src/msxout.c +0 -401
  78. epyt_flow/EPANET/EPANET-MSX/Src/msxproj.c +0 -791
  79. epyt_flow/EPANET/EPANET-MSX/Src/msxqual.c +0 -2010
  80. epyt_flow/EPANET/EPANET-MSX/Src/msxrpt.c +0 -400
  81. epyt_flow/EPANET/EPANET-MSX/Src/msxtank.c +0 -422
  82. epyt_flow/EPANET/EPANET-MSX/Src/msxtoolkit.c +0 -1164
  83. epyt_flow/EPANET/EPANET-MSX/Src/msxtypes.h +0 -551
  84. epyt_flow/EPANET/EPANET-MSX/Src/msxutils.c +0 -524
  85. epyt_flow/EPANET/EPANET-MSX/Src/msxutils.h +0 -56
  86. epyt_flow/EPANET/EPANET-MSX/Src/newton.c +0 -158
  87. epyt_flow/EPANET/EPANET-MSX/Src/newton.h +0 -34
  88. epyt_flow/EPANET/EPANET-MSX/Src/rk5.c +0 -287
  89. epyt_flow/EPANET/EPANET-MSX/Src/rk5.h +0 -39
  90. epyt_flow/EPANET/EPANET-MSX/Src/ros2.c +0 -293
  91. epyt_flow/EPANET/EPANET-MSX/Src/ros2.h +0 -35
  92. epyt_flow/EPANET/EPANET-MSX/Src/smatrix.c +0 -816
  93. epyt_flow/EPANET/EPANET-MSX/Src/smatrix.h +0 -29
  94. epyt_flow/EPANET/EPANET-MSX/readme.txt +0 -14
  95. epyt_flow/EPANET/compile_linux.sh +0 -4
  96. epyt_flow/EPANET/compile_macos.sh +0 -4
  97. epyt_flow/simulation/backend/__init__.py +0 -1
  98. epyt_flow/simulation/backend/my_epyt.py +0 -1101
  99. epyt_flow-0.14.2.dist-info/RECORD +0 -142
  100. {epyt_flow-0.14.2.dist-info → epyt_flow-0.15.0b1.dist-info}/WHEEL +0 -0
  101. {epyt_flow-0.14.2.dist-info → epyt_flow-0.15.0b1.dist-info}/licenses/LICENSE +0 -0
  102. {epyt_flow-0.14.2.dist-info → epyt_flow-0.15.0b1.dist-info}/top_level.txt +0 -0
@@ -1,720 +0,0 @@
1
- /*
2
- ******************************************************************************
3
- Project: OWA EPANET
4
- Version: 2.2
5
- Module: hydsolver.c
6
- Description: computes flows and pressures throughout a pipe network using
7
- Todini's Global Gradient Algorithm
8
- Authors: see AUTHORS
9
- Copyright: see AUTHORS
10
- License: see LICENSE
11
- Last Updated: 07/15/2019
12
- ******************************************************************************
13
- */
14
-
15
- #include <stdlib.h>
16
- #include <stdio.h>
17
- #include <string.h>
18
- #include <math.h>
19
-
20
- #include "types.h"
21
- #include "funcs.h"
22
- #include "text.h"
23
-
24
- // Hydraulic balance error for network being analyzed
25
- typedef struct {
26
- double maxheaderror;
27
- double maxflowerror;
28
- double maxflowchange;
29
- int maxheadlink;
30
- int maxflownode;
31
- int maxflowlink;
32
- } Hydbalance;
33
-
34
- // Exported functions
35
- int hydsolve(Project *, int *, double *);
36
-
37
- // Imported functions
38
- extern int linsolve(Smatrix *, int); //(see SMATRIX.C)
39
- extern int valvestatus(Project *); //(see HYDSTATUS.C)
40
- extern int linkstatus(Project *); //(see HYDSTATUS.C)
41
-
42
- // Local functions
43
- static int badvalve(Project *, int);
44
- static int pswitch(Project *);
45
-
46
- static double newflows(Project *, Hydbalance *);
47
- static void newlinkflows(Project *, Hydbalance *, double *, double *);
48
- static void newemitterflows(Project *, Hydbalance *, double *, double *);
49
- static void newdemandflows(Project *, Hydbalance *, double *, double *);
50
-
51
- static void checkhydbalance(Project *, Hydbalance *);
52
- static int hasconverged(Project *, double *, Hydbalance *);
53
- static int pdaconverged(Project *);
54
- static void reporthydbal(Project *, Hydbalance *);
55
-
56
-
57
- int hydsolve(Project *pr, int *iter, double *relerr)
58
- /*
59
- **-------------------------------------------------------------------
60
- ** Input: none
61
- ** Output: *iter = # of iterations to reach solution
62
- ** *relerr = convergence error in solution
63
- ** returns error code
64
- ** Purpose: solves network nodal equations for heads and flows
65
- ** using Todini's Gradient algorithm
66
- **
67
- ** Notes: Status checks on CVs, pumps and pipes to tanks are made
68
- ** every CheckFreq iteration, up until MaxCheck iterations
69
- ** are reached. Status checks on control valves are made
70
- ** every iteration if DampLimit = 0 or only when the
71
- ** convergence error is at or below DampLimit. If DampLimit
72
- ** is > 0 then future computed flow changes are only 60% of
73
- ** their full value. A complete status check on all links
74
- ** is made when convergence is achieved. If convergence is
75
- ** not achieved in MaxIter trials and ExtraIter > 0 then
76
- ** another ExtraIter trials are made with no status changes
77
- ** made to any links and a warning message is generated.
78
- **
79
- ** This procedure calls linsolve() which appears in SMATRIX.C.
80
- **-------------------------------------------------------------------
81
- */
82
- {
83
- Network *net = &pr->network;
84
- Hydraul *hyd = &pr->hydraul;
85
- Smatrix *sm = &hyd->smatrix;
86
- Report *rpt = &pr->report;
87
-
88
- int i; // Node index
89
- int errcode = 0; // Node causing solution error
90
- int nextcheck; // Next status check trial
91
- int maxtrials; // Max. trials for convergence
92
- double newerr; // New convergence error
93
- int valveChange; // Valve status change flag
94
- int statChange; // Non-valve status change flag
95
- Hydbalance hydbal; // Hydraulic balance errors
96
- double fullDemand; // Full demand for a node (cfs)
97
-
98
- // Initialize status checking & relaxation factor
99
- nextcheck = hyd->CheckFreq;
100
- hyd->RelaxFactor = 1.0;
101
-
102
- // Initialize convergence criteria and PDA results
103
- hydbal.maxheaderror = 0.0;
104
- hydbal.maxflowchange = 0.0;
105
- hyd->DeficientNodes = 0;
106
- hyd->DemandReduction = 0.0;
107
-
108
- // Repeat iterations until convergence or trial limit is exceeded.
109
- // (ExtraIter used to increase trials in case of status cycling.)
110
- if (rpt->Statflag == FULL) writerelerr(pr, 0, 0);
111
- maxtrials = hyd->MaxIter;
112
- if (hyd->ExtraIter > 0) maxtrials += hyd->ExtraIter;
113
- *iter = 1;
114
- while (*iter <= maxtrials)
115
- {
116
- // Compute coefficient matrices A & F and solve A*H = F
117
- // where H = heads, A = Jacobian coeffs. derived from
118
- // head loss gradients, & F = flow correction terms.
119
- // Solution for H is returned in F from call to linsolve().
120
-
121
- headlosscoeffs(pr);
122
- matrixcoeffs(pr);
123
- errcode = linsolve(sm, net->Njuncs);
124
-
125
- // Matrix ill-conditioning problem - if control valve causing problem,
126
- // fix its status & continue, otherwise quit with no solution.
127
- if (errcode > 0)
128
- {
129
- if (badvalve(pr, sm->Order[errcode])) continue;
130
- else break;
131
- }
132
-
133
- // Update current solution.
134
- // (Row[i] = row of solution matrix corresponding to node i)
135
- for (i = 1; i <= net->Njuncs; i++)
136
- {
137
- hyd->NodeHead[i] = sm->F[sm->Row[i]]; // Update heads
138
- }
139
- newerr = newflows(pr, &hydbal); // Update flows
140
- *relerr = newerr;
141
-
142
- // Write convergence error to status report if called for
143
- if (rpt->Statflag == FULL)
144
- {
145
- writerelerr(pr, *iter, *relerr);
146
- }
147
-
148
- // Apply solution damping & check for change in valve status
149
- hyd->RelaxFactor = 1.0;
150
- valveChange = FALSE;
151
- if (hyd->DampLimit > 0.0)
152
- {
153
- if (*relerr <= hyd->DampLimit)
154
- {
155
- hyd->RelaxFactor = 0.6;
156
- valveChange = valvestatus(pr);
157
- }
158
- }
159
- else
160
- {
161
- valveChange = valvestatus(pr);
162
- }
163
-
164
- // Check for convergence
165
- if (hasconverged(pr, relerr, &hydbal))
166
- {
167
- // We have convergence - quit if we are into extra iterations
168
- if (*iter > hyd->MaxIter) break;
169
-
170
- // Quit if no status changes occur
171
- statChange = FALSE;
172
- if (valveChange) statChange = TRUE;
173
- if (linkstatus(pr)) statChange = TRUE;
174
- if (pswitch(pr)) statChange = TRUE;
175
- if (!statChange) break;
176
-
177
- // We have a status change so continue the iterations
178
- nextcheck = *iter + hyd->CheckFreq;
179
- }
180
-
181
- // No convergence yet - see if its time for a periodic status
182
- // check on pumps, CV's, and pipes connected to tank
183
- else if (*iter <= hyd->MaxCheck && *iter == nextcheck)
184
- {
185
- linkstatus(pr);
186
- nextcheck += hyd->CheckFreq;
187
- }
188
- (*iter)++;
189
- }
190
-
191
- // Iterations ended - report any errors.
192
- if (errcode > 0)
193
- {
194
- writehyderr(pr, sm->Order[errcode]); // Ill-conditioned matrix error
195
- errcode = 110;
196
- }
197
-
198
- // Store actual junction outflow in NodeDemand & full demand in DemandFlow
199
- for (i = 1; i <= net->Njuncs; i++)
200
- {
201
- fullDemand = hyd->NodeDemand[i];
202
- hyd->NodeDemand[i] = hyd->DemandFlow[i] + hyd->EmitterFlow[i];
203
- hyd->DemandFlow[i] = fullDemand;
204
- }
205
-
206
- // Save convergence info
207
- hyd->RelativeError = *relerr;
208
- hyd->MaxHeadError = hydbal.maxheaderror;
209
- hyd->MaxFlowChange = hydbal.maxflowchange;
210
- hyd->Iterations = *iter;
211
- return errcode;
212
- }
213
-
214
-
215
- int badvalve(Project *pr, int n)
216
- /*
217
- **-----------------------------------------------------------------
218
- ** Input: n = node index
219
- ** Output: returns 1 if node n belongs to an active control valve,
220
- ** 0 otherwise
221
- ** Purpose: determines if a node belongs to an active control valve
222
- ** whose setting causes an inconsistent set of eqns. If so,
223
- ** the valve status is fixed open and a warning condition
224
- ** is generated.
225
- **-----------------------------------------------------------------
226
- */
227
- {
228
- Network *net = &pr->network;
229
- Hydraul *hyd = &pr->hydraul;
230
- Report *rpt = &pr->report;
231
- Times *time = &pr->times;
232
-
233
- int i, k, n1, n2;
234
- Slink *link;
235
- LinkType t;
236
-
237
- for (i = 1; i <= net->Nvalves; i++)
238
- {
239
- k = net->Valve[i].Link;
240
- link = &net->Link[k];
241
- n1 = link->N1;
242
- n2 = link->N2;
243
- if (n == n1 || n == n2)
244
- {
245
- t = link->Type;
246
- if (t == PRV || t == PSV || t == FCV)
247
- {
248
- if (hyd->LinkStatus[k] == ACTIVE)
249
- {
250
- if (rpt->Statflag == FULL)
251
- {
252
- sprintf(pr->Msg, FMT61,
253
- clocktime(rpt->Atime, time->Htime), link->ID);
254
- writeline(pr, pr->Msg);
255
- }
256
- if (link->Type == FCV) hyd->LinkStatus[k] = XFCV;
257
- else hyd->LinkStatus[k] = XPRESSURE;
258
- return 1;
259
- }
260
- }
261
- return 0;
262
- }
263
- }
264
- return 0;
265
- }
266
-
267
-
268
- int pswitch(Project *pr)
269
- /*
270
- **--------------------------------------------------------------
271
- ** Input: none
272
- ** Output: returns 1 if status of any link changes, 0 if not
273
- ** Purpose: adjusts settings of links controlled by junction
274
- ** pressures after a hydraulic solution is found
275
- **--------------------------------------------------------------
276
- */
277
- {
278
- Network *net = &pr->network;
279
- Hydraul *hyd = &pr->hydraul;
280
- Report *rpt = &pr->report;
281
-
282
- int i, // Control statement index
283
- k, // Index of link being controlled
284
- n, // Node controlling link k
285
- reset, // Flag on control conditions
286
- change, // Flag for status or setting change
287
- anychange = 0; // Flag for 1 or more control actions
288
- char s; // Current link status
289
- Slink *link;
290
-
291
- // Check each control statement
292
- for (i = 1; i <= net->Ncontrols; i++)
293
- {
294
- reset = 0;
295
- k = net->Control[i].Link;
296
- if (k <= 0) continue;
297
-
298
- // Determine if control based on a junction, not a tank
299
- n = net->Control[i].Node;
300
- if (n > 0 && n <= net->Njuncs)
301
- {
302
- // Determine if control conditions are satisfied
303
- if (net->Control[i].Type == LOWLEVEL &&
304
- hyd->NodeHead[n] <= net->Control[i].Grade + hyd->Htol)
305
- {
306
- reset = 1;
307
- }
308
- if (net->Control[i].Type == HILEVEL &&
309
- hyd->NodeHead[n] >= net->Control[i].Grade - hyd->Htol)
310
- {
311
- reset = 1;
312
- }
313
- }
314
-
315
- // Determine if control forces a status or setting change
316
- if (reset == 1)
317
- {
318
- link = &net->Link[k];
319
- change = 0;
320
- s = hyd->LinkStatus[k];
321
- if (link->Type == PIPE)
322
- {
323
- if (s != net->Control[i].Status) change = 1;
324
- }
325
- if (link->Type == PUMP)
326
- {
327
- if (hyd->LinkSetting[k] != net->Control[i].Setting) change = 1;
328
- }
329
- if (link->Type >= PRV)
330
- {
331
- if (hyd->LinkSetting[k] != net->Control[i].Setting) change = 1;
332
- else if (hyd->LinkSetting[k] == MISSING && s != net->Control[i].Status)
333
- {
334
- change = 1;
335
- }
336
- }
337
-
338
- // If a change occurs, update status & setting
339
- if (change)
340
- {
341
- hyd->LinkStatus[k] = net->Control[i].Status;
342
- if (link->Type > PIPE)
343
- {
344
- hyd->LinkSetting[k] = net->Control[i].Setting;
345
- }
346
- if (rpt->Statflag == FULL)
347
- {
348
- writestatchange(pr, k, s, hyd->LinkStatus[k]);
349
- }
350
- anychange = 1;
351
- }
352
- }
353
- }
354
- return anychange;
355
- }
356
-
357
-
358
- double newflows(Project *pr, Hydbalance *hbal)
359
- /*
360
- **----------------------------------------------------------------
361
- ** Input: hbal = ptr. to hydraulic balance information
362
- ** Output: returns solution convergence error
363
- ** Purpose: updates link, emitter & demand flows after new
364
- ** nodal heads are computed.
365
- **----------------------------------------------------------------
366
- */
367
- {
368
- Hydraul *hyd = &pr->hydraul;
369
-
370
- double dqsum, // Network flow change
371
- qsum; // Network total flow
372
-
373
- // Initialize sum of flows & corrections
374
- qsum = 0.0;
375
- dqsum = 0.0;
376
- hbal->maxflowchange = 0.0;
377
- hbal->maxflowlink = 1;
378
- hbal->maxflownode = -1;
379
-
380
- // Update flows in all real and virtual links
381
- newlinkflows(pr, hbal, &qsum, &dqsum);
382
- newemitterflows(pr, hbal, &qsum, &dqsum);
383
- newdemandflows(pr, hbal, &qsum, &dqsum);
384
-
385
- // Return ratio of total flow corrections to total flow
386
- if (qsum > hyd->Hacc) return (dqsum / qsum);
387
- else return dqsum;
388
- }
389
-
390
-
391
- void newlinkflows(Project *pr, Hydbalance *hbal, double *qsum, double *dqsum)
392
- /*
393
- **----------------------------------------------------------------
394
- ** Input: hbal = ptr. to hydraulic balance information
395
- ** qsum = sum of current system flows
396
- ** dqsum = sum of system flow changes
397
- ** Output: updates hbal, qsum and dqsum
398
- ** Purpose: updates link flows after new nodal heads computed
399
- **----------------------------------------------------------------
400
- */
401
- {
402
- Network *net = &pr->network;
403
- Hydraul *hyd = &pr->hydraul;
404
-
405
- double dh, /* Link head loss */
406
- dq; /* Link flow change */
407
- int k, n, n1, n2;
408
- Slink *link;
409
-
410
- // Initialize net inflows (i.e., demands) at fixed grade nodes
411
- for (n = net->Njuncs + 1; n <= net->Nnodes; n++)
412
- {
413
- hyd->NodeDemand[n] = 0.0;
414
- }
415
-
416
- // Examine each link
417
- for (k = 1; k <= net->Nlinks; k++)
418
- {
419
- // Get link and its end nodes
420
- link = &net->Link[k];
421
- n1 = link->N1;
422
- n2 = link->N2;
423
-
424
- // Apply flow update formula:
425
- // dq = Y - P * (new head loss)
426
- // P = 1 / (previous head loss gradient)
427
- // Y = P * (previous head loss)
428
- // where P & Y were computed in hlosscoeff() in hydcoeffs.c
429
-
430
- dh = hyd->NodeHead[n1] - hyd->NodeHead[n2];
431
- dq = hyd->Y[k] - hyd->P[k] * dh;
432
-
433
- // Adjust flow change by the relaxation factor
434
- dq *= hyd->RelaxFactor;
435
-
436
- // Prevent flow in constant HP pumps from going negative
437
- if (link->Type == PUMP)
438
- {
439
- n = findpump(net, k);
440
- if (net->Pump[n].Ptype == CONST_HP && dq > hyd->LinkFlow[k])
441
- {
442
- dq = hyd->LinkFlow[k] / 2.0;
443
- }
444
- }
445
-
446
- // Update link flow and system flow summation
447
- hyd->LinkFlow[k] -= dq;
448
- *qsum += ABS(hyd->LinkFlow[k]);
449
- *dqsum += ABS(dq);
450
-
451
- // Update identity of element with max. flow change
452
- if (ABS(dq) > hbal->maxflowchange)
453
- {
454
- hbal->maxflowchange = ABS(dq);
455
- hbal->maxflowlink = k;
456
- hbal->maxflownode = -1;
457
- }
458
-
459
- // Update net flows to fixed grade nodes
460
- if (hyd->LinkStatus[k] > CLOSED)
461
- {
462
- if (n1 > net->Njuncs) hyd->NodeDemand[n1] -= hyd->LinkFlow[k];
463
- if (n2 > net->Njuncs) hyd->NodeDemand[n2] += hyd->LinkFlow[k];
464
- }
465
- }
466
- }
467
-
468
-
469
- void newemitterflows(Project *pr, Hydbalance *hbal, double *qsum,
470
- double *dqsum)
471
- /*
472
- **----------------------------------------------------------------
473
- ** Input: hbal = ptr. to hydraulic balance information
474
- ** qsum = sum of current system flows
475
- ** dqsum = sum of system flow changes
476
- ** Output: updates hbal, qsum and dqsum
477
- ** Purpose: updates nodal emitter flows after new nodal heads computed
478
- **----------------------------------------------------------------
479
- */
480
- {
481
- Network *net = &pr->network;
482
- Hydraul *hyd = &pr->hydraul;
483
-
484
- int i;
485
- double hloss, hgrad, dh, dq;
486
-
487
- // Examine each network junction
488
- for (i = 1; i <= net->Njuncs; i++)
489
- {
490
- // Skip junction if it does not have an emitter
491
- if (net->Node[i].Ke == 0.0) continue;
492
-
493
- // Find emitter head loss and gradient
494
- emitterheadloss(pr, i, &hloss, &hgrad);
495
-
496
- // Find emitter flow change
497
- dh = hyd->NodeHead[i] - net->Node[i].El;
498
- dq = (hloss - dh) / hgrad;
499
- dq *= hyd->RelaxFactor;
500
- hyd->EmitterFlow[i] -= dq;
501
-
502
- // Update system flow summation
503
- *qsum += ABS(hyd->EmitterFlow[i]);
504
- *dqsum += ABS(dq);
505
-
506
- // Update identity of element with max. flow change
507
- if (ABS(dq) > hbal->maxflowchange)
508
- {
509
- hbal->maxflowchange = ABS(dq);
510
- hbal->maxflownode = i;
511
- hbal->maxflowlink = -1;
512
- }
513
- }
514
- }
515
-
516
-
517
- void newdemandflows(Project *pr, Hydbalance *hbal, double *qsum, double *dqsum)
518
- /*
519
- **----------------------------------------------------------------
520
- ** Input: hbal = ptr. to hydraulic balance information
521
- ** qsum = sum of current system flows
522
- ** dqsum = sum of system flow changes
523
- ** Output: updates hbal, qsum and dqsum
524
- ** Purpose: updates nodal pressure dependent demand flows after
525
- ** new nodal heads computed
526
- **----------------------------------------------------------------
527
- */
528
- {
529
- Network *net = &pr->network;
530
- Hydraul *hyd = &pr->hydraul;
531
-
532
- double dp, // pressure range over which demand can vary (ft)
533
- dq, // change in demand flow (cfs)
534
- n, // exponent in head loss v. demand function
535
- hloss, // current head loss through outflow junction (ft)
536
- hgrad, // head loss gradient with respect to flow (ft/cfs)
537
- dh; // new head loss through outflow junction (ft)
538
- int i;
539
-
540
- // Get demand function parameters
541
- if (hyd->DemandModel == DDA) return;
542
- dp = MAX((hyd->Preq - hyd->Pmin), MINPDIFF);
543
- n = 1.0 / hyd->Pexp;
544
-
545
- // Examine each junction
546
- for (i = 1; i <= net->Njuncs; i++)
547
- {
548
- // Skip junctions with no positive demand
549
- if (hyd->NodeDemand[i] <= 0.0) continue;
550
-
551
- // Find change in demand flow (see hydcoeffs.c)
552
- demandheadloss(pr, i, dp, n, &hloss, &hgrad);
553
- dh = hyd->NodeHead[i] - net->Node[i].El - hyd->Pmin;
554
- dq = (hloss - dh) / hgrad;
555
- dq *= hyd->RelaxFactor;
556
- hyd->DemandFlow[i] -= dq;
557
-
558
- // Update system flow summation
559
- *qsum += ABS(hyd->DemandFlow[i]);
560
- *dqsum += ABS(dq);
561
-
562
- // Update identity of element with max. flow change
563
- if (ABS(dq) > hbal->maxflowchange)
564
- {
565
- hbal->maxflowchange = ABS(dq);
566
- hbal->maxflownode = i;
567
- hbal->maxflowlink = -1;
568
- }
569
- }
570
- }
571
-
572
-
573
- void checkhydbalance(Project *pr, Hydbalance *hbal)
574
- /*
575
- **--------------------------------------------------------------
576
- ** Input: hbal = hydraulic balance errors
577
- ** Output: none
578
- ** Purpose: finds the link with the largest head imbalance
579
- **--------------------------------------------------------------
580
- */
581
- {
582
- Network *net = &pr->network;
583
- Hydraul *hyd = &pr->hydraul;
584
-
585
- int k, n1, n2;
586
- double dh, headerror, headloss;
587
- Slink *link;
588
-
589
- hbal->maxheaderror = 0.0;
590
- hbal->maxheadlink = 1;
591
- headlosscoeffs(pr);
592
- for (k = 1; k <= net->Nlinks; k++)
593
- {
594
- if (hyd->LinkStatus[k] <= CLOSED) continue;
595
- if (hyd->P[k] == 0.0) continue;
596
- link = &net->Link[k];
597
- n1 = link->N1;
598
- n2 = link->N2;
599
- dh = hyd->NodeHead[n1] - hyd->NodeHead[n2];
600
- headloss = hyd->Y[k] / hyd->P[k];
601
- headerror = ABS(dh - headloss);
602
- if (headerror > hbal->maxheaderror)
603
- {
604
- hbal->maxheaderror = headerror;
605
- hbal->maxheadlink = k;
606
- }
607
- }
608
- }
609
-
610
-
611
- int hasconverged(Project *pr, double *relerr, Hydbalance *hbal)
612
- /*
613
- **--------------------------------------------------------------
614
- ** Input: relerr = current total relative flow change
615
- ** hbal = current hydraulic balance errors
616
- ** Output: returns 1 if system has converged or 0 if not
617
- ** Purpose: checks various criteria to see if system has
618
- ** become hydraulically balanced
619
- **--------------------------------------------------------------
620
- */
621
- {
622
- Hydraul *hyd = &pr->hydraul;
623
-
624
- // Check that total relative flow change is small enough
625
- if (*relerr > hyd->Hacc) return 0;
626
-
627
- // Find largest head loss error and absolute flow change
628
- checkhydbalance(pr, hbal);
629
- if (pr->report.Statflag == FULL)
630
- {
631
- reporthydbal(pr, hbal);
632
- }
633
-
634
- // Check that head loss error and flow change criteria are met
635
- if (hyd->HeadErrorLimit > 0.0 &&
636
- hbal->maxheaderror > hyd->HeadErrorLimit) return 0;
637
- if (hyd->FlowChangeLimit > 0.0 &&
638
- hbal->maxflowchange > hyd->FlowChangeLimit) return 0;
639
-
640
- // Check for pressure driven analysis convergence
641
- if (hyd->DemandModel == PDA) return pdaconverged(pr);
642
- return 1;
643
- }
644
-
645
- int pdaconverged(Project *pr)
646
- /*
647
- **--------------------------------------------------------------
648
- ** Input: none
649
- ** Output: returns 1 if PDA converged, 0 if not
650
- ** Purpose: checks if pressure driven analysis has converged
651
- ** and updates total demand deficit
652
- **--------------------------------------------------------------
653
- */
654
- {
655
- Hydraul *hyd = &pr->hydraul;
656
-
657
- const double TOL = 0.001;
658
- int i, converged = 1;
659
- double totalDemand = 0.0, totalReduction = 0.0;
660
-
661
- hyd->DeficientNodes = 0;
662
- hyd->DemandReduction = 0.0;
663
-
664
- // Add up number of junctions with demand deficits
665
- for (i = 1; i <= pr->network.Njuncs; i++)
666
- {
667
- // Skip nodes whose required demand is non-positive
668
- if (hyd->NodeDemand[i] <= 0.0) continue;
669
-
670
- // Check for negative demand flow or positive demand flow at negative pressure
671
- if (hyd->DemandFlow[i] < -TOL) converged = 0;
672
- if (hyd->DemandFlow[i] > TOL &&
673
- hyd->NodeHead[i] - pr->network.Node[i].El - hyd->Pmin < -TOL)
674
- converged = 0;
675
-
676
- // Accumulate total required demand and demand deficit
677
- if (hyd->DemandFlow[i] + 0.0001 < hyd->NodeDemand[i])
678
- {
679
- hyd->DeficientNodes++;
680
- totalDemand += hyd->NodeDemand[i];
681
- totalReduction += hyd->NodeDemand[i] - hyd->DemandFlow[i];
682
- }
683
- }
684
- if (totalDemand > 0.0)
685
- hyd->DemandReduction = totalReduction / totalDemand * 100.0;
686
- return converged;
687
- }
688
-
689
-
690
- void reporthydbal(Project *pr, Hydbalance *hbal)
691
- /*
692
- **--------------------------------------------------------------
693
- ** Input: hbal = current hydraulic balance errors
694
- ** Output: none
695
- ** Purpose: identifies links with largest flow change and
696
- ** largest head loss error.
697
- **--------------------------------------------------------------
698
- */
699
- {
700
- double qchange = hbal->maxflowchange * pr->Ucf[FLOW];
701
- double herror = hbal->maxheaderror * pr->Ucf[HEAD];
702
- int qlink = hbal->maxflowlink;
703
- int qnode = hbal->maxflownode;
704
- int hlink = hbal->maxheadlink;
705
- if (qlink >= 1)
706
- {
707
- sprintf(pr->Msg, FMT66, qchange, pr->network.Link[qlink].ID);
708
- writeline(pr, pr->Msg);
709
- }
710
- else if (qnode >= 1)
711
- {
712
- sprintf(pr->Msg, FMT67, qchange, pr->network.Node[qnode].ID);
713
- writeline(pr, pr->Msg);
714
- }
715
- if (hlink >= 1)
716
- {
717
- sprintf(pr->Msg, FMT68, herror, pr->network.Link[hlink].ID);
718
- writeline(pr, pr->Msg);
719
- }
720
- }