epyt-flow 0.14.0__py3-none-any.whl → 0.14.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS +40 -8
- epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +3 -3
- epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +24 -7
- epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +726 -374
- epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +128 -32
- epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +7 -1
- epyt_flow/EPANET/EPANET/SRC_engines/flowbalance.c +186 -0
- epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +40 -14
- epyt_flow/EPANET/EPANET/SRC_engines/hash.c +177 -177
- epyt_flow/EPANET/EPANET/SRC_engines/hash.h +28 -28
- epyt_flow/EPANET/EPANET/SRC_engines/hydcoeffs.c +192 -40
- epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +101 -46
- epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +85 -24
- epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +29 -63
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +70 -37
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +408 -234
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +87 -37
- epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +153 -79
- epyt_flow/EPANET/EPANET/SRC_engines/input1.c +59 -94
- epyt_flow/EPANET/EPANET/SRC_engines/input2.c +73 -202
- epyt_flow/EPANET/EPANET/SRC_engines/input3.c +446 -351
- epyt_flow/EPANET/EPANET/SRC_engines/leakage.c +527 -0
- epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +8 -4
- epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +23 -23
- epyt_flow/EPANET/EPANET/SRC_engines/output.c +5 -4
- epyt_flow/EPANET/EPANET/SRC_engines/project.c +407 -75
- epyt_flow/EPANET/EPANET/SRC_engines/quality.c +12 -2
- epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +70 -13
- epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +7 -5
- epyt_flow/EPANET/EPANET/SRC_engines/report.c +88 -20
- epyt_flow/EPANET/EPANET/SRC_engines/rules.c +144 -6
- epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +19 -19
- epyt_flow/EPANET/EPANET/SRC_engines/text.h +16 -5
- epyt_flow/EPANET/EPANET/SRC_engines/types.h +73 -19
- epyt_flow/EPANET/EPANET/SRC_engines/util/cstr_helper.c +59 -0
- epyt_flow/EPANET/EPANET/SRC_engines/util/cstr_helper.h +38 -0
- epyt_flow/EPANET/EPANET/SRC_engines/util/errormanager.c +92 -0
- epyt_flow/EPANET/EPANET/SRC_engines/util/errormanager.h +39 -0
- epyt_flow/EPANET/EPANET/SRC_engines/util/filemanager.c +212 -0
- epyt_flow/EPANET/EPANET/SRC_engines/util/filemanager.h +81 -0
- epyt_flow/EPANET/EPANET/SRC_engines/validate.c +408 -0
- epyt_flow/EPANET/compile_linux.sh +1 -1
- epyt_flow/EPANET/compile_macos.sh +1 -1
- epyt_flow/VERSION +1 -1
- epyt_flow/gym/scenario_control_env.py +26 -3
- epyt_flow/simulation/events/quality_events.py +6 -6
- epyt_flow/simulation/events/sensor_faults.py +24 -24
- epyt_flow/simulation/events/system_event.py +3 -3
- epyt_flow/simulation/scada/scada_data.py +1 -1
- epyt_flow/simulation/scenario_simulator.py +14 -11
- epyt_flow/topology.py +8 -1
- epyt_flow/uncertainty/model_uncertainty.py +292 -150
- {epyt_flow-0.14.0.dist-info → epyt_flow-0.14.1.dist-info}/METADATA +2 -2
- {epyt_flow-0.14.0.dist-info → epyt_flow-0.14.1.dist-info}/RECORD +57 -51
- epyt_flow/EPANET/EPANET/SRC_engines/Readme_SRC_Engines.txt +0 -18
- epyt_flow/EPANET/EPANET/SRC_engines/epanet2.def +0 -131
- epyt_flow/EPANET/EPANET/SRC_engines/main.c +0 -93
- {epyt_flow-0.14.0.dist-info → epyt_flow-0.14.1.dist-info}/WHEEL +0 -0
- {epyt_flow-0.14.0.dist-info → epyt_flow-0.14.1.dist-info}/licenses/LICENSE +0 -0
- {epyt_flow-0.14.0.dist-info → epyt_flow-0.14.1.dist-info}/top_level.txt +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/*
|
|
2
2
|
******************************************************************************
|
|
3
3
|
Project: OWA EPANET
|
|
4
|
-
Version: 2.
|
|
4
|
+
Version: 2.3
|
|
5
5
|
Module: hydraul.c
|
|
6
6
|
Description: implements EPANET's hydraulic engine
|
|
7
7
|
Authors: see AUTHORS
|
|
8
8
|
Copyright: see AUTHORS
|
|
9
9
|
License: see LICENSE
|
|
10
|
-
Last Updated:
|
|
10
|
+
Last Updated: 04/19/2025
|
|
11
11
|
******************************************************************************
|
|
12
12
|
*/
|
|
13
13
|
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
const double QZERO = 1.e-6; // Equivalent to zero flow in cfs
|
|
24
24
|
|
|
25
25
|
// Imported functions
|
|
26
|
+
extern int validateproject(Project *);
|
|
26
27
|
extern int createsparse(Project *);
|
|
27
28
|
extern void freesparse(Project *);
|
|
28
29
|
extern int hydsolve(Project *, int *, double *);
|
|
@@ -34,11 +35,11 @@ void initlinkflow(Project *, int, char, double);
|
|
|
34
35
|
void demands(Project *);
|
|
35
36
|
int controls(Project *);
|
|
36
37
|
long timestep(Project *);
|
|
37
|
-
void controltimestep(Project *, long *);
|
|
38
38
|
void ruletimestep(Project *, long *);
|
|
39
39
|
void addenergy(Project *, long);
|
|
40
40
|
void tanklevels(Project *, long);
|
|
41
41
|
void resetpumpflow(Project *, int);
|
|
42
|
+
void getallpumpsenergy(Project *);
|
|
42
43
|
|
|
43
44
|
int openhyd(Project *pr)
|
|
44
45
|
/*
|
|
@@ -52,33 +53,27 @@ int openhyd(Project *pr)
|
|
|
52
53
|
int i;
|
|
53
54
|
int errcode = 0;
|
|
54
55
|
Slink *link;
|
|
55
|
-
|
|
56
|
-
// Check for
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
|
|
57
|
+
// Check for valid project data (see VALIDATE.C)
|
|
58
|
+
errcode = validateproject(pr);
|
|
59
|
+
if (errcode > 0) return errcode;
|
|
59
60
|
|
|
60
61
|
// Allocate memory for sparse matrix structures (see SMATRIX.C)
|
|
61
62
|
ERRCODE(createsparse(pr));
|
|
62
63
|
|
|
63
64
|
// Allocate memory for hydraulic variables
|
|
64
65
|
ERRCODE(allocmatrix(pr));
|
|
65
|
-
|
|
66
|
+
|
|
66
67
|
// Check for unconnected nodes
|
|
67
|
-
|
|
68
|
-
{
|
|
69
|
-
if (pr->network.Adjlist[i] == NULL)
|
|
70
|
-
{
|
|
71
|
-
errcode = 233;
|
|
72
|
-
break;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
68
|
+
ERRCODE(unlinked(pr));
|
|
75
69
|
|
|
76
70
|
// Initialize link flows
|
|
77
71
|
if (!errcode) for (i = 1; i <= pr->network.Nlinks; i++)
|
|
78
72
|
{
|
|
79
73
|
link = &pr->network.Link[i];
|
|
80
|
-
initlinkflow(pr, i, link->
|
|
74
|
+
initlinkflow(pr, i, link->InitStatus, link->Kc);
|
|
81
75
|
}
|
|
76
|
+
else closehyd(pr);
|
|
82
77
|
return errcode;
|
|
83
78
|
}
|
|
84
79
|
|
|
@@ -112,8 +107,10 @@ void inithyd(Project *pr, int initflag)
|
|
|
112
107
|
hyd->OldStatus[net->Nlinks+i] = TEMPCLOSED;
|
|
113
108
|
}
|
|
114
109
|
|
|
115
|
-
// Initialize
|
|
110
|
+
// Initialize node outflows
|
|
111
|
+
memset(hyd->DemandFlow,0,(net->Nnodes+1)*sizeof(double));
|
|
116
112
|
memset(hyd->EmitterFlow,0,(net->Nnodes+1)*sizeof(double));
|
|
113
|
+
memset(hyd->LeakageFlow,0,(net->Nnodes+1)*sizeof(double));
|
|
117
114
|
for (i = 1; i <= net->Nnodes; i++)
|
|
118
115
|
{
|
|
119
116
|
net->Node[i].ResultIndex = i;
|
|
@@ -127,9 +124,22 @@ void inithyd(Project *pr, int initflag)
|
|
|
127
124
|
link->ResultIndex = i;
|
|
128
125
|
|
|
129
126
|
// Initialize status and setting
|
|
130
|
-
hyd->LinkStatus[i] = link->
|
|
131
|
-
hyd->LinkSetting[i] = link->
|
|
132
|
-
|
|
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
|
+
|
|
133
143
|
// Compute flow resistance
|
|
134
144
|
resistcoeff(pr, i);
|
|
135
145
|
|
|
@@ -163,7 +173,12 @@ void inithyd(Project *pr, int initflag)
|
|
|
163
173
|
pump->Energy.KwHrsPerFlow = 0.0;
|
|
164
174
|
pump->Energy.MaxKwatts = 0.0;
|
|
165
175
|
pump->Energy.TotalCost = 0.0;
|
|
176
|
+
pump->Energy.CurrentPower = 0.0;
|
|
177
|
+
pump->Energy.CurrentEffic = 0.0;
|
|
166
178
|
}
|
|
179
|
+
|
|
180
|
+
// Initialize flow balance
|
|
181
|
+
startflowbalance(pr);
|
|
167
182
|
|
|
168
183
|
// Re-position hydraulics file
|
|
169
184
|
if (pr->outfile.Saveflag)
|
|
@@ -196,7 +211,7 @@ int runhyd(Project *pr, long *t)
|
|
|
196
211
|
int iter; // Iteration count
|
|
197
212
|
int errcode; // Error code
|
|
198
213
|
double relerr; // Solution accuracy
|
|
199
|
-
|
|
214
|
+
|
|
200
215
|
// Find new demands & control actions
|
|
201
216
|
*t = time->Htime;
|
|
202
217
|
demands(pr);
|
|
@@ -239,6 +254,9 @@ int nexthyd(Project *pr, long *tstep)
|
|
|
239
254
|
long hydstep; // Actual time step
|
|
240
255
|
int errcode = 0; // Error code
|
|
241
256
|
|
|
257
|
+
// Compute current power and efficiency of all pumps
|
|
258
|
+
getallpumpsenergy(pr);
|
|
259
|
+
|
|
242
260
|
// Save current results to hydraulics file and
|
|
243
261
|
// force end of simulation if Haltflag is active
|
|
244
262
|
if (pr->outfile.Saveflag) errcode = savehyd(pr, &time->Htime);
|
|
@@ -250,9 +268,12 @@ int nexthyd(Project *pr, long *tstep)
|
|
|
250
268
|
if (time->Htime < time->Dur) hydstep = timestep(pr);
|
|
251
269
|
if (pr->outfile.Saveflag) errcode = savehydstep(pr,&hydstep);
|
|
252
270
|
|
|
253
|
-
//
|
|
271
|
+
// Accumulate pumping energy
|
|
254
272
|
if (time->Dur == 0) addenergy(pr,0);
|
|
255
273
|
else if (time->Htime < time->Dur) addenergy(pr,hydstep);
|
|
274
|
+
|
|
275
|
+
// Update flow balance
|
|
276
|
+
updateflowbalance(pr, hydstep);
|
|
256
277
|
|
|
257
278
|
// More time remains - update current time
|
|
258
279
|
if (time->Htime < time->Dur)
|
|
@@ -267,6 +288,8 @@ int nexthyd(Project *pr, long *tstep)
|
|
|
267
288
|
// No more time remains - force completion of analysis
|
|
268
289
|
else
|
|
269
290
|
{
|
|
291
|
+
endflowbalance(pr);
|
|
292
|
+
if (pr->report.Statflag) writeflowbalance(pr);
|
|
270
293
|
time->Htime++;
|
|
271
294
|
if (pr->quality.OpenQflag) time->Qtime++;
|
|
272
295
|
}
|
|
@@ -286,6 +309,7 @@ void closehyd(Project *pr)
|
|
|
286
309
|
{
|
|
287
310
|
freesparse(pr);
|
|
288
311
|
freematrix(pr);
|
|
312
|
+
freeadjlists(&pr->network);
|
|
289
313
|
}
|
|
290
314
|
|
|
291
315
|
|
|
@@ -305,16 +329,12 @@ int allocmatrix(Project *pr)
|
|
|
305
329
|
|
|
306
330
|
hyd->P = (double *) calloc(net->Nlinks+1,sizeof(double));
|
|
307
331
|
hyd->Y = (double *) calloc(net->Nlinks+1,sizeof(double));
|
|
308
|
-
hyd->DemandFlow = (double *) calloc(net->Nnodes + 1, sizeof(double));
|
|
309
|
-
hyd->EmitterFlow = (double *) calloc(net->Nnodes+1, sizeof(double));
|
|
310
332
|
hyd->Xflow = (double *) calloc(MAX((net->Nnodes+1), (net->Nlinks+1)),
|
|
311
333
|
sizeof(double));
|
|
312
334
|
hyd->OldStatus = (StatusType *) calloc(net->Nlinks+net->Ntanks+1,
|
|
313
335
|
sizeof(StatusType));
|
|
314
336
|
ERRCODE(MEMCHECK(hyd->P));
|
|
315
337
|
ERRCODE(MEMCHECK(hyd->Y));
|
|
316
|
-
ERRCODE(MEMCHECK(hyd->DemandFlow));
|
|
317
|
-
ERRCODE(MEMCHECK(hyd->EmitterFlow));
|
|
318
338
|
ERRCODE(MEMCHECK(hyd->Xflow));
|
|
319
339
|
ERRCODE(MEMCHECK(hyd->OldStatus));
|
|
320
340
|
return errcode;
|
|
@@ -334,8 +354,6 @@ void freematrix(Project *pr)
|
|
|
334
354
|
|
|
335
355
|
free(hyd->P);
|
|
336
356
|
free(hyd->Y);
|
|
337
|
-
free(hyd->DemandFlow);
|
|
338
|
-
free(hyd->EmitterFlow);
|
|
339
357
|
free(hyd->Xflow);
|
|
340
358
|
free(hyd->OldStatus);
|
|
341
359
|
}
|
|
@@ -397,7 +415,7 @@ void setlinkstatus(Project *pr, int index, char value, StatusType *s, double *k
|
|
|
397
415
|
if (t == PUMP)
|
|
398
416
|
{
|
|
399
417
|
*k = 1.0;
|
|
400
|
-
// Check if a re-opened pump needs its flow reset
|
|
418
|
+
// Check if a re-opened pump needs its flow reset
|
|
401
419
|
if (*s == CLOSED) resetpumpflow(pr, index);
|
|
402
420
|
}
|
|
403
421
|
if (t > PUMP && t != GPV) *k = MISSING;
|
|
@@ -457,6 +475,7 @@ void setlinksetting(Project *pr, int index, double value, StatusType *s,
|
|
|
457
475
|
else
|
|
458
476
|
{
|
|
459
477
|
if (*k == MISSING && *s <= CLOSED) *s = OPEN;
|
|
478
|
+
if (t == PCV) link->R = pcvlosscoeff(pr, index, link->Kc);
|
|
460
479
|
*k = value;
|
|
461
480
|
}
|
|
462
481
|
}
|
|
@@ -492,12 +511,14 @@ void demands(Project *pr)
|
|
|
492
511
|
{
|
|
493
512
|
// pattern period (k) = (elapsed periods) modulus (periods per pattern)
|
|
494
513
|
j = demand->Pat;
|
|
514
|
+
if (j == 0)
|
|
515
|
+
j = hyd->DefPat;
|
|
495
516
|
k = p % (long)net->Pattern[j].Length;
|
|
496
517
|
djunc = (demand->Base) * net->Pattern[j].F[k] * hyd->Dmult;
|
|
497
518
|
if (djunc > 0.0) hyd->Dsystem += djunc;
|
|
498
519
|
sum += djunc;
|
|
499
520
|
}
|
|
500
|
-
hyd->
|
|
521
|
+
hyd->FullDemand[i] = sum;
|
|
501
522
|
|
|
502
523
|
// Initialize pressure dependent demand
|
|
503
524
|
hyd->DemandFlow[i] = sum;
|
|
@@ -562,6 +583,10 @@ int controls(Project *pr)
|
|
|
562
583
|
{
|
|
563
584
|
// Make sure that link is defined
|
|
564
585
|
control = &net->Control[i];
|
|
586
|
+
if (!control->isEnabled)
|
|
587
|
+
{
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
565
590
|
reset = 0;
|
|
566
591
|
if ( (k = control->Link) <= 0) continue;
|
|
567
592
|
link = &net->Link[k];
|
|
@@ -601,15 +626,16 @@ int controls(Project *pr)
|
|
|
601
626
|
k1 = hyd->LinkSetting[k];
|
|
602
627
|
k2 = k1;
|
|
603
628
|
if (link->Type > PIPE) k2 = control->Setting;
|
|
604
|
-
|
|
629
|
+
|
|
605
630
|
// Check if a re-opened pump needs its flow reset
|
|
606
631
|
if (link->Type == PUMP && s1 == CLOSED && s2 == OPEN)
|
|
607
632
|
resetpumpflow(pr, k);
|
|
608
|
-
|
|
633
|
+
|
|
609
634
|
if (s1 != s2 || k1 != k2)
|
|
610
635
|
{
|
|
611
636
|
hyd->LinkStatus[k] = s2;
|
|
612
637
|
hyd->LinkSetting[k] = k2;
|
|
638
|
+
if (link->Type == PCV) link->R = pcvlosscoeff(pr, k, k2);
|
|
613
639
|
if (pr->report.Statflag) writecontrolaction(pr,k,i);
|
|
614
640
|
setsum++;
|
|
615
641
|
}
|
|
@@ -673,7 +699,7 @@ int tanktimestep(Project *pr, long *tstep)
|
|
|
673
699
|
Hydraul *hyd = &pr->hydraul;
|
|
674
700
|
|
|
675
701
|
int i, n, tankIdx = 0;
|
|
676
|
-
double h, q, v;
|
|
702
|
+
double h, q, v, xt;
|
|
677
703
|
long t;
|
|
678
704
|
Stank *tank;
|
|
679
705
|
|
|
@@ -696,7 +722,9 @@ int tanktimestep(Project *pr, long *tstep)
|
|
|
696
722
|
else continue;
|
|
697
723
|
|
|
698
724
|
// Find time to fill/drain tank
|
|
699
|
-
|
|
725
|
+
xt = v / q;
|
|
726
|
+
if (ABS(xt) > *tstep + 1) continue;
|
|
727
|
+
t = (long)ROUND(xt);
|
|
700
728
|
if (t > 0 && t < *tstep)
|
|
701
729
|
{
|
|
702
730
|
*tstep = t;
|
|
@@ -707,7 +735,7 @@ int tanktimestep(Project *pr, long *tstep)
|
|
|
707
735
|
}
|
|
708
736
|
|
|
709
737
|
|
|
710
|
-
|
|
738
|
+
int controltimestep(Project *pr, long *tstep)
|
|
711
739
|
/*
|
|
712
740
|
**------------------------------------------------------------------
|
|
713
741
|
** Input: *tstep = current time step
|
|
@@ -720,7 +748,7 @@ void controltimestep(Project *pr, long *tstep)
|
|
|
720
748
|
Network *net = &pr->network;
|
|
721
749
|
Hydraul *hyd = &pr->hydraul;
|
|
722
750
|
|
|
723
|
-
int i, j, k, n;
|
|
751
|
+
int i, j, k, n, controlIndex = 0;
|
|
724
752
|
double h, q, v;
|
|
725
753
|
long t, t1, t2;
|
|
726
754
|
Slink *link;
|
|
@@ -731,7 +759,10 @@ void controltimestep(Project *pr, long *tstep)
|
|
|
731
759
|
{
|
|
732
760
|
t = 0;
|
|
733
761
|
control = &net->Control[i];
|
|
734
|
-
|
|
762
|
+
if (!control->isEnabled)
|
|
763
|
+
{
|
|
764
|
+
continue;
|
|
765
|
+
}
|
|
735
766
|
// Control depends on a tank level
|
|
736
767
|
if ( (n = control->Node) > 0)
|
|
737
768
|
{
|
|
@@ -777,9 +808,14 @@ void controltimestep(Project *pr, long *tstep)
|
|
|
777
808
|
k = control->Link;
|
|
778
809
|
link = &net->Link[k];
|
|
779
810
|
if ( (link->Type > PIPE && hyd->LinkSetting[k] != control->Setting)
|
|
780
|
-
|
|
811
|
+
|| (hyd->LinkStatus[k] != control->Status) )
|
|
812
|
+
{
|
|
813
|
+
*tstep = t;
|
|
814
|
+
controlIndex = i;
|
|
815
|
+
}
|
|
781
816
|
}
|
|
782
817
|
}
|
|
818
|
+
return controlIndex;
|
|
783
819
|
}
|
|
784
820
|
|
|
785
821
|
|
|
@@ -902,7 +938,7 @@ void addenergy(Project *pr, long hstep)
|
|
|
902
938
|
// Skip closed pumps
|
|
903
939
|
pump = &net->Pump[j];
|
|
904
940
|
k = pump->Link;
|
|
905
|
-
if (
|
|
941
|
+
if (pump->Energy.CurrentEffic == 0.0) continue;
|
|
906
942
|
q = MAX(QZERO, ABS(hyd->LinkFlow[k]));
|
|
907
943
|
|
|
908
944
|
// Find pump-specific energy cost
|
|
@@ -915,11 +951,10 @@ void addenergy(Project *pr, long hstep)
|
|
|
915
951
|
}
|
|
916
952
|
else c *= f0;
|
|
917
953
|
|
|
918
|
-
// Find pump energy & efficiency
|
|
919
|
-
getenergy(pr, k, &p, &e);
|
|
920
|
-
psum += p;
|
|
921
|
-
|
|
922
954
|
// Update pump's cumulative statistics
|
|
955
|
+
p = pump->Energy.CurrentPower;
|
|
956
|
+
e = pump->Energy.CurrentEffic;
|
|
957
|
+
psum += p;
|
|
923
958
|
pump->Energy.TimeOnLine += dt;
|
|
924
959
|
pump->Energy.Efficiency += e * dt;
|
|
925
960
|
pump->Energy.KwHrsPerFlow += p / q * dt;
|
|
@@ -995,6 +1030,27 @@ void getenergy(Project *pr, int k, double *kw, double *eff)
|
|
|
995
1030
|
}
|
|
996
1031
|
|
|
997
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
|
+
|
|
998
1054
|
void tanklevels(Project *pr, long tstep)
|
|
999
1055
|
/*
|
|
1000
1056
|
**----------------------------------------------------------------
|
|
@@ -1112,6 +1168,5 @@ void resetpumpflow(Project *pr, int i)
|
|
|
1112
1168
|
Network *net = &pr->network;
|
|
1113
1169
|
Spump *pump = &net->Pump[findpump(net, i)];
|
|
1114
1170
|
if (pump->Ptype == CONST_HP)
|
|
1115
|
-
pr->hydraul.LinkFlow[i] = pump->Q0;
|
|
1171
|
+
pr->hydraul.LinkFlow[i] = pump->Q0;
|
|
1116
1172
|
}
|
|
1117
|
-
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/*
|
|
2
2
|
******************************************************************************
|
|
3
3
|
Project: OWA EPANET
|
|
4
|
-
Version: 2.
|
|
4
|
+
Version: 2.3
|
|
5
5
|
Module: hydsolver.c
|
|
6
6
|
Description: computes flows and pressures throughout a pipe network using
|
|
7
7
|
Todini's Global Gradient Algorithm
|
|
8
8
|
Authors: see AUTHORS
|
|
9
9
|
Copyright: see AUTHORS
|
|
10
10
|
License: see LICENSE
|
|
11
|
-
Last Updated:
|
|
11
|
+
Last Updated: 06/26/2024
|
|
12
12
|
******************************************************************************
|
|
13
13
|
*/
|
|
14
14
|
|
|
@@ -47,6 +47,7 @@ static double newflows(Project *, Hydbalance *);
|
|
|
47
47
|
static void newlinkflows(Project *, Hydbalance *, double *, double *);
|
|
48
48
|
static void newemitterflows(Project *, Hydbalance *, double *, double *);
|
|
49
49
|
static void newdemandflows(Project *, Hydbalance *, double *, double *);
|
|
50
|
+
static void newleakageflows(Project *, Hydbalance *, double *, double *);
|
|
50
51
|
|
|
51
52
|
static void checkhydbalance(Project *, Hydbalance *);
|
|
52
53
|
static int hasconverged(Project *, double *, Hydbalance *);
|
|
@@ -93,7 +94,6 @@ int hydsolve(Project *pr, int *iter, double *relerr)
|
|
|
93
94
|
int valveChange; // Valve status change flag
|
|
94
95
|
int statChange; // Non-valve status change flag
|
|
95
96
|
Hydbalance hydbal; // Hydraulic balance errors
|
|
96
|
-
double fullDemand; // Full demand for a node (cfs)
|
|
97
97
|
|
|
98
98
|
// Initialize status checking & relaxation factor
|
|
99
99
|
nextcheck = hyd->CheckFreq;
|
|
@@ -178,7 +178,7 @@ int hydsolve(Project *pr, int *iter, double *relerr)
|
|
|
178
178
|
nextcheck = *iter + hyd->CheckFreq;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
// No convergence yet - see if
|
|
181
|
+
// No convergence yet - see if it's time for a periodic status
|
|
182
182
|
// check on pumps, CV's, and pipes connected to tank
|
|
183
183
|
else if (*iter <= hyd->MaxCheck && *iter == nextcheck)
|
|
184
184
|
{
|
|
@@ -195,12 +195,12 @@ int hydsolve(Project *pr, int *iter, double *relerr)
|
|
|
195
195
|
errcode = 110;
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
-
//
|
|
198
|
+
// Save total outflow (NodeDemand) at each junction
|
|
199
199
|
for (i = 1; i <= net->Njuncs; i++)
|
|
200
200
|
{
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
201
|
+
hyd->NodeDemand[i] = hyd->DemandFlow[i] +
|
|
202
|
+
hyd->EmitterFlow[i] +
|
|
203
|
+
hyd->LeakageFlow[i];
|
|
204
204
|
}
|
|
205
205
|
|
|
206
206
|
// Save convergence info
|
|
@@ -381,6 +381,7 @@ double newflows(Project *pr, Hydbalance *hbal)
|
|
|
381
381
|
newlinkflows(pr, hbal, &qsum, &dqsum);
|
|
382
382
|
newemitterflows(pr, hbal, &qsum, &dqsum);
|
|
383
383
|
newdemandflows(pr, hbal, &qsum, &dqsum);
|
|
384
|
+
if (hyd->HasLeakage) newleakageflows(pr, hbal, &qsum, &dqsum);
|
|
384
385
|
|
|
385
386
|
// Return ratio of total flow corrections to total flow
|
|
386
387
|
if (qsum > hyd->Hacc) return (dqsum / qsum);
|
|
@@ -514,6 +515,45 @@ void newemitterflows(Project *pr, Hydbalance *hbal, double *qsum,
|
|
|
514
515
|
}
|
|
515
516
|
|
|
516
517
|
|
|
518
|
+
void newleakageflows(Project *pr, Hydbalance *hbal, double *qsum,
|
|
519
|
+
double *dqsum)
|
|
520
|
+
/*
|
|
521
|
+
**----------------------------------------------------------------
|
|
522
|
+
** Input: hbal = ptr. to hydraulic balance information
|
|
523
|
+
** qsum = sum of current system flows
|
|
524
|
+
** dqsum = sum of system flow changes
|
|
525
|
+
** Output: updates hbal, qsum and dqsum
|
|
526
|
+
** Purpose: updates nodal leakage flows after new nodal heads computed
|
|
527
|
+
**----------------------------------------------------------------
|
|
528
|
+
*/
|
|
529
|
+
{
|
|
530
|
+
Network *net = &pr->network;
|
|
531
|
+
Hydraul *hyd = &pr->hydraul;
|
|
532
|
+
|
|
533
|
+
int i;
|
|
534
|
+
double dq;
|
|
535
|
+
|
|
536
|
+
for (i = 1; i <= net->Njuncs; i++)
|
|
537
|
+
{
|
|
538
|
+
// Update leakage flow at node i
|
|
539
|
+
dq = leakageflowchange(pr, i);
|
|
540
|
+
if (dq == 0.0) continue;
|
|
541
|
+
|
|
542
|
+
// Update system flow summation
|
|
543
|
+
*qsum += ABS(hyd->LeakageFlow[i]);
|
|
544
|
+
*dqsum += ABS(dq);
|
|
545
|
+
|
|
546
|
+
// Update identity of element with max. flow change
|
|
547
|
+
if (ABS(dq) > hbal->maxflowchange)
|
|
548
|
+
{
|
|
549
|
+
hbal->maxflowchange = ABS(dq);
|
|
550
|
+
hbal->maxflownode = i;
|
|
551
|
+
hbal->maxflowlink = -1;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
|
|
517
557
|
void newdemandflows(Project *pr, Hydbalance *hbal, double *qsum, double *dqsum)
|
|
518
558
|
/*
|
|
519
559
|
**----------------------------------------------------------------
|
|
@@ -546,13 +586,17 @@ void newdemandflows(Project *pr, Hydbalance *hbal, double *qsum, double *dqsum)
|
|
|
546
586
|
for (i = 1; i <= net->Njuncs; i++)
|
|
547
587
|
{
|
|
548
588
|
// Skip junctions with no positive demand
|
|
549
|
-
if (hyd->
|
|
589
|
+
if (hyd->FullDemand[i] <= 0.0) continue;
|
|
550
590
|
|
|
551
591
|
// Find change in demand flow (see hydcoeffs.c)
|
|
552
592
|
demandheadloss(pr, i, dp, n, &hloss, &hgrad);
|
|
553
593
|
dh = hyd->NodeHead[i] - net->Node[i].El - hyd->Pmin;
|
|
554
594
|
dq = (hloss - dh) / hgrad;
|
|
555
595
|
dq *= hyd->RelaxFactor;
|
|
596
|
+
|
|
597
|
+
// Prevent a flow change greater than full demand
|
|
598
|
+
if (fabs(dq) > 0.4 * hyd->FullDemand[i])
|
|
599
|
+
dq = 0.4 * SGN(dq) * hyd->FullDemand[i];
|
|
556
600
|
hyd->DemandFlow[i] -= dq;
|
|
557
601
|
|
|
558
602
|
// Update system flow summation
|
|
@@ -637,11 +681,15 @@ int hasconverged(Project *pr, double *relerr, Hydbalance *hbal)
|
|
|
637
681
|
if (hyd->FlowChangeLimit > 0.0 &&
|
|
638
682
|
hbal->maxflowchange > hyd->FlowChangeLimit) return 0;
|
|
639
683
|
|
|
684
|
+
// Check for node leakage convergence
|
|
685
|
+
if (hyd->HasLeakage && !leakagehasconverged(pr)) return 0;
|
|
686
|
+
|
|
640
687
|
// Check for pressure driven analysis convergence
|
|
641
688
|
if (hyd->DemandModel == PDA) return pdaconverged(pr);
|
|
642
689
|
return 1;
|
|
643
690
|
}
|
|
644
691
|
|
|
692
|
+
|
|
645
693
|
int pdaconverged(Project *pr)
|
|
646
694
|
/*
|
|
647
695
|
**--------------------------------------------------------------
|
|
@@ -654,33 +702,46 @@ int pdaconverged(Project *pr)
|
|
|
654
702
|
{
|
|
655
703
|
Hydraul *hyd = &pr->hydraul;
|
|
656
704
|
|
|
657
|
-
const double
|
|
705
|
+
const double QTOL = 0.0001; // 0.0001 cfs ~= 0.05 gpm ~= 0.2 lpm)
|
|
658
706
|
int i, converged = 1;
|
|
707
|
+
|
|
659
708
|
double totalDemand = 0.0, totalReduction = 0.0;
|
|
660
|
-
|
|
709
|
+
double dp = hyd->Preq - hyd->Pmin;
|
|
710
|
+
double p, q, r;
|
|
711
|
+
|
|
661
712
|
hyd->DeficientNodes = 0;
|
|
662
713
|
hyd->DemandReduction = 0.0;
|
|
663
|
-
|
|
664
|
-
//
|
|
714
|
+
|
|
715
|
+
// Examine each network junction
|
|
665
716
|
for (i = 1; i <= pr->network.Njuncs; i++)
|
|
666
717
|
{
|
|
667
718
|
// Skip nodes whose required demand is non-positive
|
|
668
|
-
if (hyd->
|
|
719
|
+
if (hyd->FullDemand[i] <= 0.0) continue;
|
|
720
|
+
|
|
721
|
+
// Evaluate demand equation at current pressure solution
|
|
722
|
+
p = hyd->NodeHead[i] - pr->network.Node[i].El;
|
|
723
|
+
if (p <= hyd->Pmin)
|
|
724
|
+
q = 0.0;
|
|
725
|
+
else if (p >= hyd->Preq)
|
|
726
|
+
q = hyd->FullDemand[i];
|
|
727
|
+
else
|
|
728
|
+
{
|
|
729
|
+
r = (p - hyd->Pmin) / dp;
|
|
730
|
+
q = hyd->FullDemand[i] * pow(r, hyd->Pexp);
|
|
731
|
+
}
|
|
669
732
|
|
|
670
|
-
// Check
|
|
671
|
-
if (hyd->DemandFlow[i]
|
|
672
|
-
if (hyd->DemandFlow[i] > TOL &&
|
|
673
|
-
hyd->NodeHead[i] - pr->network.Node[i].El - hyd->Pmin < -TOL)
|
|
733
|
+
// Check if demand has not converged
|
|
734
|
+
if (fabs(q - hyd->DemandFlow[i]) > QTOL)
|
|
674
735
|
converged = 0;
|
|
675
|
-
|
|
676
|
-
// Accumulate
|
|
677
|
-
if (hyd->DemandFlow[i] +
|
|
736
|
+
|
|
737
|
+
// Accumulate demand deficient node count and demand deficit
|
|
738
|
+
if (hyd->DemandFlow[i] + QTOL < hyd->FullDemand[i])
|
|
678
739
|
{
|
|
679
740
|
hyd->DeficientNodes++;
|
|
680
|
-
totalDemand += hyd->
|
|
681
|
-
totalReduction += hyd->
|
|
741
|
+
totalDemand += hyd->FullDemand[i];
|
|
742
|
+
totalReduction += hyd->FullDemand[i] - hyd->DemandFlow[i];
|
|
682
743
|
}
|
|
683
|
-
}
|
|
744
|
+
}
|
|
684
745
|
if (totalDemand > 0.0)
|
|
685
746
|
hyd->DemandReduction = totalReduction / totalDemand * 100.0;
|
|
686
747
|
return converged;
|