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,1151 +0,0 @@
1
- /*
2
- ******************************************************************************
3
- Project: OWA EPANET
4
- Version: 2.2
5
- Module: hydcoeffs.c
6
- Description: computes coefficients for a hydraulic solution matrix
7
- Authors: see AUTHORS
8
- Copyright: see AUTHORS
9
- License: see LICENSE
10
- Last Updated: 10/04/2019
11
- ******************************************************************************
12
- */
13
-
14
- #include <stdlib.h>
15
- #include <stdio.h>
16
- #include <string.h>
17
- #include <math.h>
18
-
19
- #include "types.h"
20
- #include "funcs.h"
21
-
22
- // Constants used for computing Darcy-Weisbach friction factor
23
- const double A1 = 3.14159265358979323850e+03; // 1000*PI
24
- const double A2 = 1.57079632679489661930e+03; // 500*PI
25
- const double A3 = 5.02654824574366918160e+01; // 16*PI
26
- const double A4 = 6.28318530717958647700e+00; // 2*PI
27
- const double A8 = 4.61841319859066668690e+00; // 5.74*(PI/4)^.9
28
- const double A9 = -8.68588963806503655300e-01; // -2/ln(10)
29
- const double AA = -1.5634601348517065795e+00; // -2*.9*2/ln(10)
30
- const double AB = 3.28895476345399058690e-03; // 5.74/(4000^.9)
31
- const double AC = -5.14214965799093883760e-03; // AA*AB
32
-
33
- // Definitions of very small and very big coefficients
34
- const double CSMALL = 1.e-6;
35
- const double CBIG = 1.e8;
36
-
37
- // Exported functions
38
- //void resistcoeff(Project *, int );
39
- //void headlosscoeffs(Project *);
40
- //void matrixcoeffs(Project *);
41
- //void emitterheadloss(Project *, int, double *, double *);
42
- //void demandheadloss(Project *, int, double, double, double *, double *);
43
-
44
- // Local functions
45
- static void linkcoeffs(Project *pr);
46
- static void nodecoeffs(Project *pr);
47
- static void valvecoeffs(Project *pr);
48
- static void emittercoeffs(Project *pr);
49
- static void demandcoeffs(Project *pr);
50
-
51
- static void pipecoeff(Project *pr, int k);
52
- static void DWpipecoeff(Project *pr, int k);
53
- static double frictionFactor(double q, double e, double s, double *dfdq);
54
-
55
- static void pumpcoeff(Project *pr, int k);
56
- static void curvecoeff(Project *pr, int i, double q, double *h0, double *r);
57
-
58
- static void valvecoeff(Project *pr, int k);
59
- static void gpvcoeff(Project *pr, int k);
60
- static void pbvcoeff(Project *pr, int k);
61
- static void tcvcoeff(Project *pr, int k);
62
- static void prvcoeff(Project *pr, int k, int n1, int n2);
63
- static void psvcoeff(Project *pr, int k, int n1, int n2);
64
- static void fcvcoeff(Project *pr, int k, int n1, int n2);
65
-
66
-
67
- void resistcoeff(Project *pr, int k)
68
- /*
69
- **--------------------------------------------------------------------
70
- ** Input: k = link index
71
- ** Output: none
72
- ** Purpose: computes link flow resistance coefficient
73
- **--------------------------------------------------------------------
74
- */
75
- {
76
- Network *net = &pr->network;
77
- Hydraul *hyd = &pr->hydraul;
78
-
79
- double e, d, L;
80
- Slink *link = &net->Link[k];
81
-
82
- switch (link->Type) {
83
-
84
- // ... Link is a pipe. Compute resistance based on headloss formula.
85
- // Friction factor for D-W formula gets included during head loss
86
- // calculation.
87
- case CVPIPE:
88
- case PIPE:
89
- e = link->Kc; // Roughness coeff.
90
- d = link->Diam; // Diameter
91
- L = link->Len; // Length
92
- switch (hyd->Formflag)
93
- {
94
- case HW:
95
- link->R = 4.727 * L / pow(e, hyd->Hexp) / pow(d, 4.871);
96
- break;
97
- case DW:
98
- link->R = L / 2.0 / 32.2 / d / SQR(PI * SQR(d) / 4.0);
99
- break;
100
- case CM:
101
- link->R = SQR(4.0 * e / (1.49 * PI * SQR(d))) *
102
- pow((d / 4.0), -1.333) * L;
103
- }
104
- break;
105
-
106
- // ... Link is a pump. Use huge resistance.
107
- case PUMP:
108
- link->R = CBIG;
109
- break;
110
-
111
- // ... For all other links (e.g. valves) use a small resistance
112
- default:
113
- link->R = CSMALL;
114
- break;
115
- }
116
- }
117
-
118
-
119
- void headlosscoeffs(Project *pr)
120
- /*
121
- **--------------------------------------------------------------
122
- ** Input: none
123
- ** Output: none
124
- ** Purpose: computes coefficients P (1 / head loss gradient)
125
- ** and Y (head loss / gradient) for all links.
126
- **--------------------------------------------------------------
127
- */
128
- {
129
- Network *net = &pr->network;
130
- Hydraul *hyd = &pr->hydraul;
131
-
132
- int k;
133
-
134
- for (k = 1; k <= net->Nlinks; k++)
135
- {
136
- switch (net->Link[k].Type)
137
- {
138
- case CVPIPE:
139
- case PIPE:
140
- pipecoeff(pr, k);
141
- break;
142
- case PUMP:
143
- pumpcoeff(pr, k);
144
- break;
145
- case PBV:
146
- pbvcoeff(pr, k);
147
- break;
148
- case TCV:
149
- tcvcoeff(pr, k);
150
- break;
151
- case GPV:
152
- gpvcoeff(pr, k);
153
- break;
154
- case FCV:
155
- case PRV:
156
- case PSV:
157
- if (hyd->LinkSetting[k] == MISSING) valvecoeff(pr, k);
158
- else hyd->P[k] = 0.0;
159
- }
160
- }
161
- }
162
-
163
-
164
- void matrixcoeffs(Project *pr)
165
- /*
166
- **--------------------------------------------------------------
167
- ** Input: none
168
- ** Output: none
169
- ** Purpose: computes coefficients of linearized network eqns.
170
- **--------------------------------------------------------------
171
- */
172
- {
173
- Network *net = &pr->network;
174
- Hydraul *hyd = &pr->hydraul;
175
- Smatrix *sm = &hyd->smatrix;
176
-
177
- // Reset values of all diagonal coeffs. (Aii), off-diagonal
178
- // coeffs. (Aij), r.h.s. coeffs. (F) and node excess flow (Xflow)
179
- memset(sm->Aii, 0, (net->Nnodes + 1) * sizeof(double));
180
- memset(sm->Aij, 0, (sm->Ncoeffs + 1) * sizeof(double));
181
- memset(sm->F, 0, (net->Nnodes + 1) * sizeof(double));
182
- memset(hyd->Xflow, 0, (net->Nnodes + 1) * sizeof(double));
183
-
184
- // Compute matrix coeffs. from links, emitters, and nodal demands
185
- linkcoeffs(pr);
186
- emittercoeffs(pr);
187
- demandcoeffs(pr);
188
-
189
- // Update nodal flow balances with demands and add onto r.h.s. coeffs.
190
- nodecoeffs(pr);
191
-
192
- // Finally, find coeffs. for PRV/PSV/FCV control valves whose
193
- // status is not fixed to OPEN/CLOSED
194
- valvecoeffs(pr);
195
- }
196
-
197
-
198
- void linkcoeffs(Project *pr)
199
- /*
200
- **--------------------------------------------------------------
201
- ** Input: none
202
- ** Output: none
203
- ** Purpose: computes coefficients contributed by links to the
204
- ** linearized system of hydraulic equations.
205
- **--------------------------------------------------------------
206
- */
207
- {
208
- Network *net = &pr->network;
209
- Hydraul *hyd = &pr->hydraul;
210
- Smatrix *sm = &hyd->smatrix;
211
-
212
- int k, n1, n2;
213
- Slink *link;
214
-
215
- // Examine each link of network
216
- for (k = 1; k <= net->Nlinks; k++)
217
- {
218
- if (hyd->P[k] == 0.0) continue;
219
- link = &net->Link[k];
220
- n1 = link->N1; // Start node of link
221
- n2 = link->N2; // End node of link
222
-
223
- // Update nodal flow excess (Xflow)
224
- // (Flow out of node is (-), flow into node is (+))
225
- hyd->Xflow[n1] -= hyd->LinkFlow[k];
226
- hyd->Xflow[n2] += hyd->LinkFlow[k];
227
-
228
- // Add to off-diagonal coeff. of linear system matrix
229
- sm->Aij[sm->Ndx[k]] -= hyd->P[k];
230
-
231
- // Update linear system coeffs. associated with start node n1
232
- // ... node n1 is junction
233
- if (n1 <= net->Njuncs)
234
- {
235
- sm->Aii[sm->Row[n1]] += hyd->P[k]; // Diagonal coeff.
236
- sm->F[sm->Row[n1]] += hyd->Y[k]; // RHS coeff.
237
- }
238
-
239
- // ... node n1 is a tank/reservoir
240
- else sm->F[sm->Row[n2]] += (hyd->P[k] * hyd->NodeHead[n1]);
241
-
242
- // Update linear system coeffs. associated with end node n2
243
- // ... node n2 is junction
244
- if (n2 <= net->Njuncs)
245
- {
246
- sm->Aii[sm->Row[n2]] += hyd->P[k]; // Diagonal coeff.
247
- sm->F[sm->Row[n2]] -= hyd->Y[k]; // RHS coeff.
248
- }
249
-
250
- // ... node n2 is a tank/reservoir
251
- else sm->F[sm->Row[n1]] += (hyd->P[k] * hyd->NodeHead[n2]);
252
- }
253
- }
254
-
255
-
256
- void nodecoeffs(Project *pr)
257
- /*
258
- **----------------------------------------------------------------
259
- ** Input: none
260
- ** Output: none
261
- ** Purpose: completes calculation of nodal flow balance array
262
- ** (Xflow) & r.h.s. (F) of linearized hydraulic eqns.
263
- **----------------------------------------------------------------
264
- */
265
- {
266
- Network *net = &pr->network;
267
- Hydraul *hyd = &pr->hydraul;
268
- Smatrix *sm = &hyd->smatrix;
269
-
270
- int i;
271
-
272
- // For junction nodes, subtract demand flow from net
273
- // flow excess & add flow excess to RHS array F
274
- for (i = 1; i <= net->Njuncs; i++)
275
- {
276
- hyd->Xflow[i] -= hyd->DemandFlow[i];
277
- sm->F[sm->Row[i]] += hyd->Xflow[i];
278
- }
279
- }
280
-
281
-
282
- void valvecoeffs(Project *pr)
283
- /*
284
- **--------------------------------------------------------------
285
- ** Input: none
286
- ** Output: none
287
- ** Purpose: computes coeffs. of the linearized hydraulic eqns.
288
- ** contributed by PRVs, PSVs & FCVs whose status is
289
- ** not fixed to OPEN/CLOSED
290
- **--------------------------------------------------------------
291
- */
292
- {
293
- Network *net = &pr->network;
294
- Hydraul *hyd = &pr->hydraul;
295
-
296
- int i, k, n1, n2;
297
- Slink *link;
298
- Svalve *valve;
299
-
300
- // Examine each valve
301
- for (i = 1; i <= net->Nvalves; i++)
302
- {
303
- // Find valve's link index
304
- valve = &net->Valve[i];
305
- k = valve->Link;
306
-
307
- // Coeffs. for fixed status valves have already been computed
308
- if (hyd->LinkSetting[k] == MISSING) continue;
309
-
310
- // Start & end nodes of valve's link
311
- link = &net->Link[k];
312
- n1 = link->N1;
313
- n2 = link->N2;
314
-
315
- // Call valve-specific function
316
- switch (link->Type)
317
- {
318
- case PRV:
319
- prvcoeff(pr, k, n1, n2);
320
- break;
321
- case PSV:
322
- psvcoeff(pr, k, n1, n2);
323
- break;
324
- case FCV:
325
- fcvcoeff(pr, k, n1, n2);
326
- break;
327
- default: continue;
328
- }
329
- }
330
- }
331
-
332
-
333
- void emittercoeffs(Project *pr)
334
- /*
335
- **--------------------------------------------------------------
336
- ** Input: none
337
- ** Output: none
338
- ** Purpose: computes coeffs. of the linearized hydraulic eqns.
339
- ** contributed by emitters.
340
- **
341
- ** Note: Emitters consist of a fictitious pipe connected to
342
- ** a fictitious reservoir whose elevation equals that
343
- ** of the junction. The headloss through this pipe is
344
- ** Ke*(Flow)^hyd->Qexp, where Ke = emitter headloss coeff.
345
- **--------------------------------------------------------------
346
- */
347
- {
348
- Network *net = &pr->network;
349
- Hydraul *hyd = &pr->hydraul;
350
- Smatrix *sm = &hyd->smatrix;
351
-
352
- int i, row;
353
- double hloss, hgrad;
354
- Snode *node;
355
-
356
- for (i = 1; i <= net->Njuncs; i++)
357
- {
358
- // Skip junctions without emitters
359
- node = &net->Node[i];
360
- if (node->Ke == 0.0) continue;
361
-
362
- // Find emitter head loss and gradient
363
- emitterheadloss(pr, i, &hloss, &hgrad);
364
-
365
- // Row of solution matrix
366
- row = sm->Row[i];
367
-
368
- // Addition to matrix diagonal & r.h.s
369
- sm->Aii[row] += 1.0 / hgrad;
370
- sm->F[row] += (hloss + node->El) / hgrad;
371
-
372
- // Update to node flow excess
373
- hyd->Xflow[i] -= hyd->EmitterFlow[i];
374
- }
375
- }
376
-
377
-
378
- void emitterheadloss(Project *pr, int i, double *hloss, double *hgrad)
379
- /*
380
- **-------------------------------------------------------------
381
- ** Input: i = node index
382
- ** Output: hloss = head loss across node's emitter
383
- ** hgrad = head loss gradient
384
- ** Purpose: computes an emitters's head loss and gradient.
385
- **-------------------------------------------------------------
386
- */
387
- {
388
- Hydraul *hyd = &pr->hydraul;
389
-
390
- double ke;
391
- double q;
392
-
393
- // Set adjusted emitter coeff.
394
- ke = MAX(CSMALL, pr->network.Node[i].Ke);
395
-
396
- // Compute gradient of head loss through emitter
397
- q = hyd->EmitterFlow[i];
398
- *hgrad = hyd->Qexp * ke * pow(fabs(q), hyd->Qexp - 1.0);
399
-
400
- // Use linear head loss function for small gradient
401
- if (*hgrad < hyd->RQtol)
402
- {
403
- *hgrad = hyd->RQtol;
404
- *hloss = (*hgrad) * q;
405
- }
406
-
407
- // Otherwise use normal emitter head loss function
408
- else *hloss = (*hgrad) * q / hyd->Qexp;
409
- }
410
-
411
-
412
- void demandcoeffs(Project *pr)
413
- /*
414
- **--------------------------------------------------------------
415
- ** Input: none
416
- ** Output: none
417
- ** Purpose: computes coeffs. of the linearized hydraulic eqns.
418
- ** contributed by pressure dependent demands.
419
- **
420
- ** Note: Pressure dependent demands are modelled like emitters
421
- ** with Hloss = Preq * (D / Dfull)^(1/Pexp)
422
- ** where D (actual demand) is zero for negative pressure
423
- ** and is Dfull above pressure Preq.
424
- **--------------------------------------------------------------
425
- */
426
- {
427
- Network *net = &pr->network;
428
- Hydraul *hyd = &pr->hydraul;
429
- Smatrix *sm = &hyd->smatrix;
430
-
431
- int i, row;
432
- double dp, // pressure range over which demand can vary (ft)
433
- n, // exponent in head loss v. demand function
434
- hloss, // head loss in supplying demand (ft)
435
- hgrad; // gradient of demand head loss (ft/cfs)
436
-
437
- // Get demand function parameters
438
- if (hyd->DemandModel == DDA) return;
439
- dp = hyd->Preq - hyd->Pmin;
440
- n = 1.0 / hyd->Pexp;
441
-
442
- // Examine each junction node
443
- for (i = 1; i <= net->Njuncs; i++)
444
- {
445
- // Skip junctions with non-positive demands
446
- if (hyd->NodeDemand[i] <= 0.0) continue;
447
-
448
- // Find head loss for demand outflow at node's elevation
449
- demandheadloss(pr, i, dp, n, &hloss, &hgrad);
450
-
451
- // Update row of solution matrix A & its r.h.s. F
452
- if (hgrad > 0.0)
453
- {
454
- row = sm->Row[i];
455
- sm->Aii[row] += 1.0 / hgrad;
456
- sm->F[row] += (hloss + net->Node[i].El + hyd->Pmin) / hgrad;
457
- }
458
- }
459
- }
460
-
461
- void demandheadloss(Project *pr, int i, double dp, double n,
462
- double *hloss, double *hgrad)
463
- /*
464
- **--------------------------------------------------------------
465
- ** Input: i = junction index
466
- ** dp = pressure range for demand function (ft)
467
- ** n = exponent in head v. demand function
468
- ** Output: hloss = pressure dependent demand head loss (ft)
469
- ** hgrad = gradient of head loss (ft/cfs)
470
- ** Purpose: computes head loss and its gradient for delivering
471
- ** a pressure dependent demand flow.
472
- **--------------------------------------------------------------
473
- */
474
- {
475
- Hydraul *hyd = &pr->hydraul;
476
-
477
- double d = hyd->DemandFlow[i];
478
- double dfull = hyd->NodeDemand[i];
479
- double r = d / dfull;
480
-
481
- // Use lower barrier function for negative demand
482
- if (r <= 0)
483
- {
484
- *hgrad = CBIG;
485
- *hloss = CBIG * d;
486
- }
487
-
488
- // Use power head loss function for demand less than full
489
- else if (r < 1.0)
490
- {
491
- *hgrad = n * dp * pow(r, n - 1.0) / dfull;
492
- // ... use linear function for very small gradient
493
- if (*hgrad < hyd->RQtol)
494
- {
495
- *hgrad = hyd->RQtol;
496
- *hloss = (*hgrad) * d;
497
- }
498
- else *hloss = (*hgrad) * d / n;
499
- }
500
-
501
- // Use upper barrier function for demand above full value
502
- else
503
- {
504
- *hgrad = CBIG;
505
- *hloss = dp + CBIG * (d - dfull);
506
- }
507
- }
508
-
509
-
510
- void pipecoeff(Project *pr, int k)
511
- /*
512
- **--------------------------------------------------------------
513
- ** Input: k = link index
514
- ** Output: none
515
- ** Purpose: computes P & Y coefficients for pipe k.
516
- **
517
- ** P = inverse head loss gradient = 1/hgrad
518
- ** Y = flow correction term = hloss / hgrad
519
- **--------------------------------------------------------------
520
- */
521
- {
522
- Hydraul *hyd = &pr->hydraul;
523
-
524
- double hloss, // Head loss
525
- hgrad, // Head loss gradient
526
- ml, // Minor loss coeff.
527
- q, // Abs. value of flow
528
- r; // Resistance coeff.
529
-
530
- // For closed pipe use headloss formula: hloss = CBIG*q
531
- if (hyd->LinkStatus[k] <= CLOSED)
532
- {
533
- hyd->P[k] = 1.0 / CBIG;
534
- hyd->Y[k] = hyd->LinkFlow[k];
535
- return;
536
- }
537
-
538
- // Use custom function for Darcy-Weisbach formula
539
- if (hyd->Formflag == DW)
540
- {
541
- DWpipecoeff(pr, k);
542
- return;
543
- }
544
-
545
- q = ABS(hyd->LinkFlow[k]);
546
- ml = pr->network.Link[k].Km;
547
- r = pr->network.Link[k].R;
548
-
549
- // Friction head loss gradient
550
- hgrad = hyd->Hexp * r * pow(q, hyd->Hexp - 1.0);
551
-
552
- // Friction head loss:
553
- // ... use linear function for very small gradient
554
- if (hgrad < hyd->RQtol)
555
- {
556
- hgrad = hyd->RQtol;
557
- hloss = hgrad * q;
558
- }
559
- // ... otherwise use original formula
560
- else hloss = hgrad * q / hyd->Hexp;
561
-
562
- // Contribution of minor head loss
563
- if (ml > 0.0)
564
- {
565
- hloss += ml * q * q;
566
- hgrad += 2.0 * ml * q;
567
- }
568
-
569
- // Adjust head loss sign for flow direction
570
- hloss *= SGN(hyd->LinkFlow[k]);
571
-
572
- // P and Y coeffs.
573
- hyd->P[k] = 1.0 / hgrad;
574
- hyd->Y[k] = hloss / hgrad;
575
- }
576
-
577
-
578
- void DWpipecoeff(Project *pr, int k)
579
- /*
580
- **--------------------------------------------------------------
581
- ** Input: k = link index
582
- ** Output: none
583
- ** Purpose: computes pipe head loss coeffs. for Darcy-Weisbach
584
- ** formula.
585
- **--------------------------------------------------------------
586
- */
587
- {
588
- Hydraul *hyd = &pr->hydraul;
589
- Slink *link = &pr->network.Link[k];
590
-
591
- double q = ABS(hyd->LinkFlow[k]);
592
- double r = link->R; // Resistance coeff.
593
- double ml = link->Km; // Minor loss coeff.
594
- double e = link->Kc / link->Diam; // Relative roughness
595
- double s = hyd->Viscos * link->Diam; // Viscosity / diameter
596
- double hloss, hgrad, f, dfdq, r1;
597
-
598
- // Compute head loss and its derivative
599
- // ... use Hagen-Poiseuille formula for laminar flow (Re <= 2000)
600
- if (q <= A2 * s)
601
- {
602
- r = 16.0 * PI * s * r;
603
- hloss = hyd->LinkFlow[k] * (r + ml * q);
604
- hgrad = r + 2.0 * ml * q;
605
- }
606
-
607
- // ... otherwise use Darcy-Weisbach formula with friction factor
608
- else
609
- {
610
- dfdq = 0.0;
611
- f = frictionFactor(q, e, s, &dfdq);
612
- r1 = f * r + ml;
613
- hloss = r1 * q * hyd->LinkFlow[k];
614
- hgrad = (2.0 * r1 * q) + (dfdq * r * q * q);
615
- }
616
-
617
- // Compute P and Y coefficients
618
- hyd->P[k] = 1.0 / hgrad;
619
- hyd->Y[k] = hloss / hgrad;
620
- }
621
-
622
-
623
- double frictionFactor(double q, double e, double s, double *dfdq)
624
- /*
625
- **--------------------------------------------------------------
626
- ** Input: q = |pipe flow|
627
- ** e = pipe roughness / diameter
628
- ** s = viscosity * pipe diameter
629
- ** Output: dfdq = derivative of friction factor w.r.t. flow
630
- ** Returns: pipe's friction factor
631
- ** Purpose: computes Darcy-Weisbach friction factor and its
632
- ** derivative as a function of Reynolds Number (Re).
633
- **--------------------------------------------------------------
634
- */
635
- {
636
- double f; // friction factor
637
- double x1, x2, x3, x4,
638
- y1, y2, y3,
639
- fa, fb, r;
640
- double w = q / s; // Re*Pi/4
641
-
642
- // For Re >= 4000 use Swamee & Jain approximation
643
- // of the Colebrook-White Formula
644
- if ( w >= A1 )
645
- {
646
- y1 = A8 / pow(w, 0.9);
647
- y2 = e / 3.7 + y1;
648
- y3 = A9 * log(y2);
649
- f = 1.0 / (y3*y3);
650
- *dfdq = 1.8 * f * y1 * A9 / y2 / y3 / q;
651
- }
652
-
653
- // Use interpolating polynomials developed by
654
- // E. Dunlop for transition flow from 2000 < Re < 4000.
655
- else
656
- {
657
- y2 = e / 3.7 + AB;
658
- y3 = A9 * log(y2);
659
- fa = 1.0 / (y3*y3);
660
- fb = (2.0 + AC / (y2*y3)) * fa;
661
- r = w / A2;
662
- x1 = 7.0 * fa - fb;
663
- x2 = 0.128 - 17.0 * fa + 2.5 * fb;
664
- x3 = -0.128 + 13.0 * fa - (fb + fb);
665
- x4 = 0.032 - 3.0 * fa + 0.5 *fb;
666
- f = x1 + r * (x2 + r * (x3 + r * x4));
667
- *dfdq = (x2 + r * (2.0 * x3 + r * 3.0 * x4)) / s / A2;
668
- }
669
- return f;
670
- }
671
-
672
-
673
- void pumpcoeff(Project *pr, int k)
674
- /*
675
- **--------------------------------------------------------------
676
- ** Input: k = link index
677
- ** Output: none
678
- ** Purpose: computes P & Y coeffs. for pump in link k
679
- **--------------------------------------------------------------
680
- */
681
- {
682
- Hydraul *hyd = &pr->hydraul;
683
-
684
- int p; // Pump index
685
- double h0, // Shutoff head
686
- q, // Abs. value of flow
687
- r, // Flow resistance coeff.
688
- n, // Flow exponent coeff.
689
- setting, // Pump speed setting
690
- hloss, // Head loss across pump
691
- hgrad; // Head loss gradient
692
- Spump *pump;
693
-
694
- // Use high resistance pipe if pump closed or cannot deliver head
695
- setting = hyd->LinkSetting[k];
696
- if (hyd->LinkStatus[k] <= CLOSED || setting == 0.0)
697
- {
698
- hyd->P[k] = 1.0 / CBIG;
699
- hyd->Y[k] = hyd->LinkFlow[k];
700
- return;
701
- }
702
-
703
- // Obtain reference to pump object
704
- q = ABS(hyd->LinkFlow[k]);
705
- p = findpump(&pr->network, k);
706
- pump = &pr->network.Pump[p];
707
-
708
- // If no pump curve treat pump as an open valve
709
- if (pump->Ptype == NOCURVE)
710
- {
711
- hyd->P[k] = 1.0 / CSMALL;
712
- hyd->Y[k] = hyd->LinkFlow[k];
713
- return;
714
- }
715
-
716
- // Get pump curve coefficients for custom pump curve
717
- // (Other pump types have pre-determined coeffs.)
718
- if (pump->Ptype == CUSTOM)
719
- {
720
- // Find intercept (h0) & slope (r) of pump curve
721
- // line segment which contains speed-adjusted flow.
722
- curvecoeff(pr, pump->Hcurve, q / setting, &h0, &r);
723
-
724
- // Determine head loss coefficients (negative sign
725
- // converts from pump curve's head gain to head loss)
726
- pump->H0 = -h0;
727
- pump->R = -r;
728
- pump->N = 1.0;
729
-
730
- // Compute head loss and its gradient (with speed adjustment)
731
- hgrad = pump->R * setting ;
732
- hloss = pump->H0 * SQR(setting) + hgrad * hyd->LinkFlow[k];
733
- }
734
- else
735
- {
736
- // Adjust head loss coefficients for pump speed
737
- h0 = SQR(setting) * pump->H0;
738
- n = pump->N;
739
- if (ABS(n - 1.0) < TINY) n = 1.0;
740
- r = pump->R * pow(setting, 2.0 - n);
741
-
742
- // Constant HP pump
743
- if (pump->Ptype == CONST_HP)
744
- {
745
- // ... compute pump curve's gradient
746
- hgrad = -r / q / q;
747
- // ... use linear curve if gradient too large or too small
748
- if (hgrad > CBIG)
749
- {
750
- hgrad = CBIG;
751
- hloss = -hgrad * hyd->LinkFlow[k];
752
- }
753
- else if (hgrad < hyd->RQtol)
754
- {
755
- hgrad = hyd->RQtol;
756
- hloss = -hgrad * hyd->LinkFlow[k];
757
- }
758
- // ... otherwise compute head loss from pump curve
759
- else
760
- {
761
- hloss = r / hyd->LinkFlow[k];
762
- }
763
- }
764
-
765
- // Compute head loss and its gradient
766
- // ... pump curve is nonlinear
767
- else if (n != 1.0)
768
- {
769
- // ... compute pump curve's gradient
770
- hgrad = n * r * pow(q, n - 1.0);
771
- // ... use linear pump curve if gradient too small
772
- if (hgrad < hyd->RQtol)
773
- {
774
- hgrad = hyd->RQtol;
775
- hloss = h0 + hgrad * hyd->LinkFlow[k];
776
- }
777
- // ... otherwise compute head loss from pump curve
778
- else hloss = h0 + hgrad * hyd->LinkFlow[k] / n;
779
- }
780
- // ... pump curve is linear
781
- else
782
- {
783
- hgrad = r;
784
- hloss = h0 + hgrad * hyd->LinkFlow[k];
785
- }
786
- }
787
-
788
- // P and Y coeffs.
789
- hyd->P[k] = 1.0 / hgrad;
790
- hyd->Y[k] = hloss / hgrad;
791
- }
792
-
793
-
794
- void curvecoeff(Project *pr, int i, double q, double *h0, double *r)
795
- /*
796
- **-------------------------------------------------------------------
797
- ** Input: i = curve index
798
- ** q = flow rate
799
- ** Output: *h0 = head at zero flow (y-intercept)
800
- ** *r = dHead/dFlow (slope)
801
- ** Purpose: computes intercept and slope of head v. flow curve
802
- ** at current flow.
803
- **-------------------------------------------------------------------
804
- */
805
- {
806
- int k1, k2, npts;
807
- double *x, *y;
808
- Scurve *curve;
809
-
810
- // Remember that curve is stored in untransformed units
811
- q *= pr->Ucf[FLOW];
812
- curve = &pr->network.Curve[i];
813
- x = curve->X; // x = flow
814
- y = curve->Y; // y = head
815
- npts = curve->Npts;
816
-
817
- // Find linear segment of curve that brackets flow q
818
- k2 = 0;
819
- while (k2 < npts && x[k2] < q) k2++;
820
- if (k2 == 0) k2++;
821
- else if (k2 == npts) k2--;
822
- k1 = k2 - 1;
823
-
824
- // Compute slope and intercept of this segment
825
- *r = (y[k2] - y[k1]) / (x[k2] - x[k1]);
826
- *h0 = y[k1] - (*r)*x[k1];
827
-
828
- // Convert units
829
- *h0 = (*h0) / pr->Ucf[HEAD];
830
- *r = (*r) * pr->Ucf[FLOW] / pr->Ucf[HEAD];
831
- }
832
-
833
-
834
- void gpvcoeff(Project *pr, int k)
835
- /*
836
- **--------------------------------------------------------------
837
- ** Input: k = link index
838
- ** Output: none
839
- ** Purpose: computes P & Y coeffs. for general purpose valve
840
- **--------------------------------------------------------------
841
- */
842
- {
843
- int i;
844
- double h0, // Intercept of head loss curve segment
845
- r, // Slope of head loss curve segment
846
- q; // Abs. value of flow
847
-
848
- Hydraul *hyd = &pr->hydraul;
849
-
850
- // Treat as a pipe if valve closed
851
- if (hyd->LinkStatus[k] == CLOSED) valvecoeff(pr, k);
852
-
853
- // Otherwise utilize segment of head loss curve
854
- // bracketing current flow (curve index is stored
855
- // in valve's setting)
856
- else
857
- {
858
- // Index of valve's head loss curve
859
- i = (int)ROUND(hyd->LinkSetting[k]);
860
-
861
- // Adjusted flow rate
862
- q = ABS(hyd->LinkFlow[k]);
863
- q = MAX(q, TINY);
864
-
865
- // Intercept and slope of curve segment containing q
866
- curvecoeff(pr, i, q, &h0, &r);
867
- r = MAX(r, TINY);
868
-
869
- // Resulting P and Y coeffs.
870
- hyd->P[k] = 1.0 / r;
871
- hyd->Y[k] = (h0 / r + q) * SGN(hyd->LinkFlow[k]);
872
- }
873
- }
874
-
875
-
876
- void pbvcoeff(Project *pr, int k)
877
- /*
878
- **--------------------------------------------------------------
879
- ** Input: k = link index
880
- ** Output: none
881
- ** Purpose: computes P & Y coeffs. for pressure breaker valve
882
- **--------------------------------------------------------------
883
- */
884
- {
885
- Hydraul *hyd = &pr->hydraul;
886
- Slink *link = &pr->network.Link[k];
887
-
888
- // If valve fixed OPEN or CLOSED then treat as a pipe
889
- if (hyd->LinkSetting[k] == MISSING || hyd->LinkSetting[k] == 0.0)
890
- {
891
- valvecoeff(pr, k);
892
- }
893
-
894
- // If valve is active
895
- else
896
- {
897
- // Treat as a pipe if minor loss > valve setting
898
- if (link->Km * SQR(hyd->LinkFlow[k]) > hyd->LinkSetting[k])
899
- {
900
- valvecoeff(pr, k);
901
- }
902
- // Otherwise force headloss across valve to be equal to setting
903
- else
904
- {
905
- hyd->P[k] = CBIG;
906
- hyd->Y[k] = hyd->LinkSetting[k] * CBIG;
907
- }
908
- }
909
- }
910
-
911
-
912
- void tcvcoeff(Project *pr, int k)
913
- /*
914
- **--------------------------------------------------------------
915
- ** Input: k = link index
916
- ** Output: none
917
- ** Purpose: computes P & Y coeffs. for throttle control valve
918
- **--------------------------------------------------------------
919
- */
920
- {
921
- double km;
922
- Hydraul *hyd = &pr->hydraul;
923
- Slink *link = &pr->network.Link[k];
924
-
925
- // Save original loss coeff. for open valve
926
- km = link->Km;
927
-
928
- // If valve not fixed OPEN or CLOSED, compute its loss coeff.
929
- if (hyd->LinkSetting[k] != MISSING)
930
- {
931
- link->Km = 0.02517 * hyd->LinkSetting[k] / (SQR(link->Diam)*SQR(link->Diam));
932
- }
933
-
934
- // Then apply usual valve formula
935
- valvecoeff(pr, k);
936
-
937
- // Restore original loss coeff.
938
- link->Km = km;
939
- }
940
-
941
-
942
- void prvcoeff(Project *pr, int k, int n1, int n2)
943
- /*
944
- **--------------------------------------------------------------
945
- ** Input: k = link index
946
- ** n1 = upstream node of valve
947
- ** n2 = downstream node of valve
948
- ** Output: none
949
- ** Purpose: computes solution matrix coeffs. for pressure
950
- ** reducing valves
951
- **--------------------------------------------------------------
952
- */
953
- {
954
- Hydraul *hyd = &pr->hydraul;
955
- Smatrix *sm = &hyd->smatrix;
956
-
957
- int i, j; // Rows of solution matrix
958
- double hset; // Valve head setting
959
-
960
- i = sm->Row[n1]; // Matrix rows of nodes
961
- j = sm->Row[n2];
962
- hset = pr->network.Node[n2].El +
963
- hyd->LinkSetting[k]; // Valve setting
964
-
965
- if (hyd->LinkStatus[k] == ACTIVE)
966
- {
967
-
968
- // Set coeffs. to force head at downstream
969
- // node equal to valve setting & force flow
970
- // to equal to flow excess at downstream node.
971
-
972
- hyd->P[k] = 0.0;
973
- hyd->Y[k] = hyd->LinkFlow[k] + hyd->Xflow[n2]; // Force flow balance
974
- sm->F[j] += (hset * CBIG); // Force head = hset
975
- sm->Aii[j] += CBIG; // at downstream node
976
- if (hyd->Xflow[n2] < 0.0)
977
- {
978
- sm->F[i] += hyd->Xflow[n2];
979
- }
980
- return;
981
- }
982
-
983
- // For OPEN, CLOSED, or XPRESSURE valve
984
- // compute matrix coeffs. using the valvecoeff() function.
985
-
986
- valvecoeff(pr, k);
987
- sm->Aij[sm->Ndx[k]] -= hyd->P[k];
988
- sm->Aii[i] += hyd->P[k];
989
- sm->Aii[j] += hyd->P[k];
990
- sm->F[i] += (hyd->Y[k] - hyd->LinkFlow[k]);
991
- sm->F[j] -= (hyd->Y[k] - hyd->LinkFlow[k]);
992
- }
993
-
994
-
995
- void psvcoeff(Project *pr, int k, int n1, int n2)
996
- /*
997
- **--------------------------------------------------------------
998
- ** Input: k = link index
999
- ** n1 = upstream node of valve
1000
- ** n2 = downstream node of valve
1001
- ** Output: none
1002
- ** Purpose: computes solution matrix coeffs. for pressure
1003
- ** sustaining valve
1004
- **--------------------------------------------------------------
1005
- */
1006
- {
1007
- Hydraul *hyd = &pr->hydraul;
1008
- Smatrix *sm = &hyd->smatrix;
1009
-
1010
- int i, j; // Rows of solution matrix
1011
- double hset; // Valve head setting
1012
-
1013
- i = sm->Row[n1]; // Matrix rows of nodes
1014
- j = sm->Row[n2];
1015
- hset = pr->network.Node[n1].El +
1016
- hyd->LinkSetting[k]; // Valve setting
1017
-
1018
- if (hyd->LinkStatus[k] == ACTIVE)
1019
- {
1020
- // Set coeffs. to force head at upstream
1021
- // node equal to valve setting & force flow
1022
- // equal to flow excess at upstream node.
1023
-
1024
- hyd->P[k] = 0.0;
1025
- hyd->Y[k] = hyd->LinkFlow[k] - hyd->Xflow[n1]; // Force flow balance
1026
- sm->F[i] += (hset * CBIG); // Force head = hset
1027
- sm->Aii[i] += CBIG; // at upstream node
1028
- if (hyd->Xflow[n1] > 0.0)
1029
- {
1030
- sm->F[j] += hyd->Xflow[n1];
1031
- }
1032
- return;
1033
- }
1034
-
1035
- // For OPEN, CLOSED, or XPRESSURE valve
1036
- // compute matrix coeffs. using the valvecoeff() function.
1037
-
1038
- valvecoeff(pr, k);
1039
- sm->Aij[sm->Ndx[k]] -= hyd->P[k];
1040
- sm->Aii[i] += hyd->P[k];
1041
- sm->Aii[j] += hyd->P[k];
1042
- sm->F[i] += (hyd->Y[k] - hyd->LinkFlow[k]);
1043
- sm->F[j] -= (hyd->Y[k] - hyd->LinkFlow[k]);
1044
- }
1045
-
1046
-
1047
- void fcvcoeff(Project *pr, int k, int n1, int n2)
1048
- /*
1049
- **--------------------------------------------------------------
1050
- ** Input: k = link index
1051
- ** n1 = upstream node of valve
1052
- ** n2 = downstream node of valve
1053
- ** Output: none
1054
- ** Purpose: computes solution matrix coeffs. for flow control
1055
- ** valve
1056
- **--------------------------------------------------------------
1057
- */
1058
- {
1059
- Hydraul *hyd = &pr->hydraul;
1060
- Smatrix *sm = &hyd->smatrix;
1061
-
1062
- int i, j; // Rows in solution matrix
1063
- double q; // Valve flow setting
1064
-
1065
- q = hyd->LinkSetting[k];
1066
- i = sm->Row[n1];
1067
- j = sm->Row[n2];
1068
-
1069
- // If valve active, break network at valve and treat
1070
- // flow setting as external demand at upstream node
1071
- // and external supply at downstream node.
1072
-
1073
- if (hyd->LinkStatus[k] == ACTIVE)
1074
- {
1075
- hyd->Xflow[n1] -= q;
1076
- hyd->Xflow[n2] += q;
1077
- hyd->Y[k] = hyd->LinkFlow[k] - q;
1078
- sm->F[i] -= q;
1079
- sm->F[j] += q;
1080
- hyd->P[k] = 1.0 / CBIG;
1081
- sm->Aij[sm->Ndx[k]] -= hyd->P[k];
1082
- sm->Aii[i] += hyd->P[k];
1083
- sm->Aii[j] += hyd->P[k];
1084
- }
1085
-
1086
- // Otherwise treat valve as an open pipe
1087
-
1088
- else
1089
- {
1090
- valvecoeff(pr, k);
1091
- sm->Aij[sm->Ndx[k]] -= hyd->P[k];
1092
- sm->Aii[i] += hyd->P[k];
1093
- sm->Aii[j] += hyd->P[k];
1094
- sm->F[i] += (hyd->Y[k] - hyd->LinkFlow[k]);
1095
- sm->F[j] -= (hyd->Y[k] - hyd->LinkFlow[k]);
1096
- }
1097
- }
1098
-
1099
-
1100
- void valvecoeff(Project *pr, int k)
1101
- /*
1102
- **--------------------------------------------------------------
1103
- ** Input: k = link index
1104
- ** Output: none
1105
- ** Purpose: computes solution matrix coeffs. for a completely
1106
- ** open, closed, or throttled control valve.
1107
- **--------------------------------------------------------------
1108
- */
1109
- {
1110
- Hydraul *hyd = &pr->hydraul;
1111
- Slink *link = &pr->network.Link[k];
1112
-
1113
- double flow, q, hloss, hgrad;
1114
-
1115
- flow = hyd->LinkFlow[k];
1116
-
1117
- // Valve is closed. Use a very small matrix coeff.
1118
- if (hyd->LinkStatus[k] <= CLOSED)
1119
- {
1120
- hyd->P[k] = 1.0 / CBIG;
1121
- hyd->Y[k] = flow;
1122
- return;
1123
- }
1124
-
1125
- // Account for any minor headloss through the valve
1126
- if (link->Km > 0.0)
1127
- {
1128
- q = fabs(flow);
1129
- hgrad = 2.0 * link->Km * q;
1130
-
1131
- // Guard against too small a head loss gradient
1132
- if (hgrad < hyd->RQtol)
1133
- {
1134
- hgrad = hyd->RQtol;
1135
- hloss = flow * hgrad;
1136
- }
1137
- else hloss = flow * hgrad / 2.0;
1138
-
1139
- // P and Y coeffs.
1140
- hyd->P[k] = 1.0 / hgrad;
1141
- hyd->Y[k] = hloss / hgrad;
1142
- }
1143
-
1144
- // If no minor loss coeff. specified use a
1145
- // low resistance linear head loss relation
1146
- else
1147
- {
1148
- hyd->P[k] = 1.0 / CSMALL;
1149
- hyd->Y[k] = flow;
1150
- }
1151
- }