epyt-flow 0.13.1__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 +2 -2
- epyt_flow/VERSION +1 -1
- epyt_flow/__init__.py +1 -1
- epyt_flow/gym/scenario_control_env.py +26 -3
- epyt_flow/simulation/backend/my_epyt.py +58 -13
- 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 +10 -14
- epyt_flow/simulation/scenario_simulator.py +100 -20
- epyt_flow/topology.py +8 -1
- epyt_flow/uncertainty/model_uncertainty.py +292 -150
- epyt_flow/uncertainty/uncertainties.py +2 -2
- {epyt_flow-0.13.1.dist-info → epyt_flow-0.14.1.dist-info}/METADATA +4 -4
- {epyt_flow-0.13.1.dist-info → epyt_flow-0.14.1.dist-info}/RECORD +60 -54
- {epyt_flow-0.13.1.dist-info → epyt_flow-0.14.1.dist-info}/WHEEL +1 -1
- 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.13.1.dist-info → epyt_flow-0.14.1.dist-info}/licenses/LICENSE +0 -0
- {epyt_flow-0.13.1.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: project.c
|
|
6
6
|
Description: project data management routines
|
|
7
7
|
Authors: see AUTHORS
|
|
8
8
|
Copyright: see AUTHORS
|
|
9
9
|
License: see LICENSE
|
|
10
|
-
Last Updated:
|
|
10
|
+
Last Updated: 04/23/2025
|
|
11
11
|
******************************************************************************
|
|
12
12
|
*/
|
|
13
13
|
|
|
@@ -24,6 +24,81 @@
|
|
|
24
24
|
#include "types.h"
|
|
25
25
|
#include "funcs.h"
|
|
26
26
|
|
|
27
|
+
int openproject(Project *pr, const char *inpFile, const char *rptFile,
|
|
28
|
+
const char *outFile, int allowerrors)
|
|
29
|
+
/*----------------------------------------------------------------
|
|
30
|
+
** Input: inpFile = name of input file
|
|
31
|
+
** rptFile = name of report file
|
|
32
|
+
** outFile = name of binary output file
|
|
33
|
+
** allowerrors = TRUE if project can be opened with errors
|
|
34
|
+
** Output: none
|
|
35
|
+
** Returns: error code
|
|
36
|
+
** Purpose: opens an EPANET input file & reads in network data
|
|
37
|
+
**----------------------------------------------------------------
|
|
38
|
+
*/
|
|
39
|
+
{
|
|
40
|
+
int errcode = 0;
|
|
41
|
+
int hyderrcode = 0;
|
|
42
|
+
int projectopened;
|
|
43
|
+
|
|
44
|
+
// Set system flags
|
|
45
|
+
pr->Openflag = FALSE;
|
|
46
|
+
pr->hydraul.OpenHflag = FALSE;
|
|
47
|
+
pr->quality.OpenQflag = FALSE;
|
|
48
|
+
pr->outfile.SaveHflag = FALSE;
|
|
49
|
+
pr->outfile.SaveQflag = FALSE;
|
|
50
|
+
pr->Warnflag = FALSE;
|
|
51
|
+
pr->report.Messageflag = TRUE;
|
|
52
|
+
pr->report.Rptflag = 1;
|
|
53
|
+
|
|
54
|
+
// Initialize data arrays to NULL
|
|
55
|
+
initpointers(pr);
|
|
56
|
+
|
|
57
|
+
// Open input & report files
|
|
58
|
+
ERRCODE(openfiles(pr, inpFile, rptFile, outFile));
|
|
59
|
+
if (errcode > 0)
|
|
60
|
+
{
|
|
61
|
+
errmsg(pr, errcode);
|
|
62
|
+
return errcode;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Allocate memory for project's data arrays
|
|
66
|
+
ERRCODE(netsize(pr));
|
|
67
|
+
ERRCODE(allocdata(pr));
|
|
68
|
+
|
|
69
|
+
// Read input data
|
|
70
|
+
ERRCODE(getdata(pr));
|
|
71
|
+
|
|
72
|
+
// Close input file
|
|
73
|
+
if (pr->parser.InFile != NULL)
|
|
74
|
+
{
|
|
75
|
+
fclose(pr->parser.InFile);
|
|
76
|
+
pr->parser.InFile = NULL;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Input file read with no fatal errors
|
|
80
|
+
if (allowerrors) projectopened = (errcode == 0 || errcode == 200);
|
|
81
|
+
else projectopened = (errcode == 0);
|
|
82
|
+
if (projectopened)
|
|
83
|
+
{
|
|
84
|
+
// If using previously saved hydraulics file then open it
|
|
85
|
+
if (pr->outfile.Hydflag == USE)
|
|
86
|
+
{
|
|
87
|
+
hyderrcode = openhydfile(pr);
|
|
88
|
+
if (hyderrcode > 0)
|
|
89
|
+
{
|
|
90
|
+
errmsg(pr, hyderrcode);
|
|
91
|
+
pr->outfile.Hydflag = SCRATCH;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Write input summary to report file
|
|
96
|
+
if (pr->report.Summaryflag) writesummary(pr);
|
|
97
|
+
pr->Openflag = TRUE;
|
|
98
|
+
}
|
|
99
|
+
errmsg(pr, errcode);
|
|
100
|
+
return errcode;
|
|
101
|
+
}
|
|
27
102
|
|
|
28
103
|
int openfiles(Project *pr, const char *f1, const char *f2, const char *f3)
|
|
29
104
|
/*----------------------------------------------------------------
|
|
@@ -93,10 +168,9 @@ int openhydfile(Project *pr)
|
|
|
93
168
|
INT4 version;
|
|
94
169
|
int errcode = 0;
|
|
95
170
|
|
|
96
|
-
// If HydFile currently open, then close it
|
|
171
|
+
// If HydFile currently open, then close it
|
|
97
172
|
if (pr->outfile.HydFile != NULL)
|
|
98
173
|
{
|
|
99
|
-
if (pr->outfile.Hydflag == SCRATCH) return 0;
|
|
100
174
|
fclose(pr->outfile.HydFile);
|
|
101
175
|
pr->outfile.HydFile = NULL;
|
|
102
176
|
}
|
|
@@ -253,6 +327,11 @@ void initpointers(Project *pr)
|
|
|
253
327
|
pr->hydraul.P = NULL;
|
|
254
328
|
pr->hydraul.Y = NULL;
|
|
255
329
|
pr->hydraul.Xflow = NULL;
|
|
330
|
+
pr->hydraul.FullDemand = NULL;
|
|
331
|
+
pr->hydraul.DemandFlow = NULL;
|
|
332
|
+
pr->hydraul.EmitterFlow = NULL;
|
|
333
|
+
pr->hydraul.LeakageFlow = NULL;
|
|
334
|
+
pr->hydraul.Leakage = NULL;
|
|
256
335
|
|
|
257
336
|
pr->quality.NodeQual = NULL;
|
|
258
337
|
pr->quality.PipeRateCoeff = NULL;
|
|
@@ -279,6 +358,8 @@ void initpointers(Project *pr)
|
|
|
279
358
|
pr->hydraul.smatrix.NZSUB = NULL;
|
|
280
359
|
pr->hydraul.smatrix.LNZ = NULL;
|
|
281
360
|
|
|
361
|
+
pr->report.reportCallback = NULL;
|
|
362
|
+
|
|
282
363
|
initrules(pr);
|
|
283
364
|
}
|
|
284
365
|
|
|
@@ -313,10 +394,18 @@ int allocdata(Project *pr)
|
|
|
313
394
|
pr->hydraul.NodeDemand = (double *)calloc(n, sizeof(double));
|
|
314
395
|
pr->hydraul.NodeHead = (double *)calloc(n, sizeof(double));
|
|
315
396
|
pr->quality.NodeQual = (double *)calloc(n, sizeof(double));
|
|
397
|
+
pr->hydraul.FullDemand = (double *)calloc(n, sizeof(double));
|
|
398
|
+
pr->hydraul.DemandFlow = (double *)calloc(n, sizeof(double));
|
|
399
|
+
pr->hydraul.EmitterFlow = (double *)calloc(n, sizeof(double));
|
|
400
|
+
pr->hydraul.LeakageFlow = (double *)calloc(n, sizeof(double));
|
|
316
401
|
ERRCODE(MEMCHECK(pr->network.Node));
|
|
317
402
|
ERRCODE(MEMCHECK(pr->hydraul.NodeDemand));
|
|
318
403
|
ERRCODE(MEMCHECK(pr->hydraul.NodeHead));
|
|
319
404
|
ERRCODE(MEMCHECK(pr->quality.NodeQual));
|
|
405
|
+
ERRCODE(MEMCHECK(pr->hydraul.FullDemand));
|
|
406
|
+
ERRCODE(MEMCHECK(pr->hydraul.DemandFlow));
|
|
407
|
+
ERRCODE(MEMCHECK(pr->hydraul.EmitterFlow));
|
|
408
|
+
ERRCODE(MEMCHECK(pr->hydraul.LeakageFlow));
|
|
320
409
|
}
|
|
321
410
|
|
|
322
411
|
// Allocate memory for network links
|
|
@@ -359,11 +448,13 @@ int allocdata(Project *pr)
|
|
|
359
448
|
pr->network.Node[n].D = NULL; // node demand
|
|
360
449
|
pr->network.Node[n].S = NULL; // node source
|
|
361
450
|
pr->network.Node[n].Comment = NULL;
|
|
451
|
+
pr->network.Node[n].Tag = NULL;
|
|
362
452
|
}
|
|
363
453
|
for (n = 0; n <= pr->parser.MaxLinks; n++)
|
|
364
454
|
{
|
|
365
455
|
pr->network.Link[n].Vertices = NULL;
|
|
366
456
|
pr->network.Link[n].Comment = NULL;
|
|
457
|
+
pr->network.Link[n].Tag = NULL;
|
|
367
458
|
}
|
|
368
459
|
}
|
|
369
460
|
|
|
@@ -388,6 +479,10 @@ void freedata(Project *pr)
|
|
|
388
479
|
free(pr->hydraul.LinkFlow);
|
|
389
480
|
free(pr->hydraul.LinkSetting);
|
|
390
481
|
free(pr->hydraul.LinkStatus);
|
|
482
|
+
free(pr->hydraul.FullDemand);
|
|
483
|
+
free(pr->hydraul.DemandFlow);
|
|
484
|
+
free(pr->hydraul.EmitterFlow);
|
|
485
|
+
free(pr->hydraul.LeakageFlow);
|
|
391
486
|
free(pr->quality.NodeQual);
|
|
392
487
|
|
|
393
488
|
// Free memory used for nodal adjacency lists
|
|
@@ -402,6 +497,7 @@ void freedata(Project *pr)
|
|
|
402
497
|
freedemands(&(pr->network.Node[j]));
|
|
403
498
|
free(pr->network.Node[j].S);
|
|
404
499
|
free(pr->network.Node[j].Comment);
|
|
500
|
+
free(pr->network.Node[j].Tag);
|
|
405
501
|
}
|
|
406
502
|
free(pr->network.Node);
|
|
407
503
|
}
|
|
@@ -413,6 +509,7 @@ void freedata(Project *pr)
|
|
|
413
509
|
{
|
|
414
510
|
freelinkvertices(&pr->network.Link[j]);
|
|
415
511
|
free(pr->network.Link[j].Comment);
|
|
512
|
+
free(pr->network.Link[j].Tag);
|
|
416
513
|
}
|
|
417
514
|
}
|
|
418
515
|
free(pr->network.Link);
|
|
@@ -482,7 +579,7 @@ Pdemand finddemand(Pdemand d, int index)
|
|
|
482
579
|
return d;
|
|
483
580
|
}
|
|
484
581
|
|
|
485
|
-
int adddemand(Snode *node, double dbase, int dpat, char *dname)
|
|
582
|
+
int adddemand(Snode *node, double dbase, int dpat, const char *dname)
|
|
486
583
|
/*----------------------------------------------------------------
|
|
487
584
|
** Input: node = a network junction node
|
|
488
585
|
** dbase = base demand value
|
|
@@ -550,31 +647,41 @@ int addlinkvertex(Slink *link, double x, double y)
|
|
|
550
647
|
*/
|
|
551
648
|
{
|
|
552
649
|
static int CHUNKSIZE = 5;
|
|
553
|
-
int n;
|
|
650
|
+
int n, newCapacity;
|
|
554
651
|
Pvertices vertices;
|
|
555
|
-
|
|
652
|
+
double *newX, *newY;
|
|
653
|
+
|
|
654
|
+
vertices = link->Vertices;
|
|
655
|
+
if (vertices == NULL)
|
|
556
656
|
{
|
|
557
657
|
vertices = (struct Svertices *) malloc(sizeof(struct Svertices));
|
|
558
658
|
if (vertices == NULL) return 101;
|
|
559
659
|
vertices->Npts = 0;
|
|
560
|
-
vertices->Capacity =
|
|
561
|
-
vertices->X =
|
|
562
|
-
vertices->Y =
|
|
660
|
+
vertices->Capacity = 0;
|
|
661
|
+
vertices->X = NULL;
|
|
662
|
+
vertices->Y = NULL;
|
|
563
663
|
link->Vertices = vertices;
|
|
564
664
|
}
|
|
565
|
-
vertices = link->Vertices;
|
|
566
665
|
if (vertices->Npts >= vertices->Capacity)
|
|
567
666
|
{
|
|
568
|
-
vertices->Capacity
|
|
569
|
-
|
|
570
|
-
|
|
667
|
+
newCapacity = vertices->Capacity + CHUNKSIZE;
|
|
668
|
+
newX = realloc(vertices->X, newCapacity * sizeof(double));
|
|
669
|
+
newY = realloc(vertices->Y, newCapacity * sizeof(double));
|
|
670
|
+
if (newX == NULL || newY == NULL)
|
|
671
|
+
{
|
|
672
|
+
free(newX);
|
|
673
|
+
free(newY);
|
|
674
|
+
return 101;
|
|
675
|
+
}
|
|
676
|
+
vertices->Capacity = newCapacity;
|
|
677
|
+
vertices->X = newX;
|
|
678
|
+
vertices->Y = newY;
|
|
571
679
|
}
|
|
572
|
-
if (vertices->X == NULL || vertices->Y == NULL) return 101;
|
|
573
680
|
n = vertices->Npts;
|
|
574
681
|
vertices->X[n] = x;
|
|
575
682
|
vertices->Y[n] = y;
|
|
576
683
|
vertices->Npts++;
|
|
577
|
-
return 0;
|
|
684
|
+
return 0;
|
|
578
685
|
}
|
|
579
686
|
|
|
580
687
|
void freelinkvertices(Slink *link)
|
|
@@ -647,7 +754,6 @@ int buildadjlists(Network *net)
|
|
|
647
754
|
return errcode;
|
|
648
755
|
}
|
|
649
756
|
|
|
650
|
-
|
|
651
757
|
void freeadjlists(Network *net)
|
|
652
758
|
/*
|
|
653
759
|
**--------------------------------------------------------------
|
|
@@ -734,6 +840,66 @@ int incontrols(Project *pr, int objType, int index)
|
|
|
734
840
|
return 0;
|
|
735
841
|
}
|
|
736
842
|
|
|
843
|
+
int changevalvetype(Project *pr, int index, int type)
|
|
844
|
+
/*
|
|
845
|
+
**--------------------------------------------------------------
|
|
846
|
+
** Input: index = link index
|
|
847
|
+
** type = new valve type
|
|
848
|
+
** Output: returns an error code
|
|
849
|
+
** Purpose: changes a valve's type
|
|
850
|
+
**--------------------------------------------------------------
|
|
851
|
+
*/
|
|
852
|
+
{
|
|
853
|
+
Network *net = &pr->network;
|
|
854
|
+
Slink *link;
|
|
855
|
+
int errcode;
|
|
856
|
+
double setting;
|
|
857
|
+
|
|
858
|
+
// Check that new valve type has legal connections
|
|
859
|
+
link = &net->Link[index];
|
|
860
|
+
if (link->Type <= PUMP) return 264;
|
|
861
|
+
errcode = valvecheck(pr, index, type, link->N1, link->N2);
|
|
862
|
+
if (errcode) return errcode;
|
|
863
|
+
|
|
864
|
+
// Preserve new type's setting in solver units
|
|
865
|
+
setting = link->InitSetting;
|
|
866
|
+
switch (link->Type)
|
|
867
|
+
{
|
|
868
|
+
case FCV:
|
|
869
|
+
setting *= pr->Ucf[FLOW];
|
|
870
|
+
break;
|
|
871
|
+
case PRV:
|
|
872
|
+
case PSV:
|
|
873
|
+
case PBV:
|
|
874
|
+
setting *= pr->Ucf[PRESSURE];
|
|
875
|
+
break;
|
|
876
|
+
case GPV:
|
|
877
|
+
setting = 0.0;
|
|
878
|
+
break;
|
|
879
|
+
}
|
|
880
|
+
switch (type)
|
|
881
|
+
{
|
|
882
|
+
case FCV:
|
|
883
|
+
setting /= pr->Ucf[FLOW];
|
|
884
|
+
break;
|
|
885
|
+
case PRV:
|
|
886
|
+
case PSV:
|
|
887
|
+
case PBV:
|
|
888
|
+
setting /= pr->Ucf[PRESSURE];
|
|
889
|
+
break;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
// Save setting
|
|
893
|
+
if (type == GPV) setting = 0.0;
|
|
894
|
+
if (type == PCV) setting = MIN(setting, 100.0);
|
|
895
|
+
link->Kc = setting;
|
|
896
|
+
link->InitSetting = setting;
|
|
897
|
+
|
|
898
|
+
// Change valve link's type
|
|
899
|
+
link->Type = type;
|
|
900
|
+
return 0;
|
|
901
|
+
}
|
|
902
|
+
|
|
737
903
|
int valvecheck(Project *pr, int index, int type, int j1, int j2)
|
|
738
904
|
/*
|
|
739
905
|
**--------------------------------------------------------------
|
|
@@ -795,7 +961,36 @@ int valvecheck(Project *pr, int index, int type, int j1, int j2)
|
|
|
795
961
|
return 0;
|
|
796
962
|
}
|
|
797
963
|
|
|
798
|
-
int
|
|
964
|
+
int unlinked(Project *pr)
|
|
965
|
+
/*
|
|
966
|
+
**--------------------------------------------------------------
|
|
967
|
+
** Input: none
|
|
968
|
+
** Output: returns error code if any unlinked junctions found
|
|
969
|
+
** Purpose: checks for unlinked junctions in network
|
|
970
|
+
**
|
|
971
|
+
** NOTE: unlinked tanks have no effect on computations.
|
|
972
|
+
**--------------------------------------------------------------
|
|
973
|
+
*/
|
|
974
|
+
{
|
|
975
|
+
Network *net = &pr->network;
|
|
976
|
+
int i, count = 0;
|
|
977
|
+
char errmsg[MAXMSG + 1] = "";
|
|
978
|
+
|
|
979
|
+
for (i = 1; i <= net->Njuncs; i++)
|
|
980
|
+
{
|
|
981
|
+
if (pr->network.Adjlist[i] == NULL)
|
|
982
|
+
{
|
|
983
|
+
count++;
|
|
984
|
+
sprintf(pr->Msg, "Error 234: %s %s", geterrmsg(234, errmsg), net->Node[i].ID);
|
|
985
|
+
writeline(pr, pr->Msg);
|
|
986
|
+
}
|
|
987
|
+
if (count >= 10) break;
|
|
988
|
+
}
|
|
989
|
+
if (count > 0) return 233;
|
|
990
|
+
return 0;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
int findnode(Network *network, const char *id)
|
|
799
994
|
/*----------------------------------------------------------------
|
|
800
995
|
** Input: id = node ID
|
|
801
996
|
** Output: none
|
|
@@ -807,7 +1002,7 @@ int findnode(Network *network, char *id)
|
|
|
807
1002
|
return (hashtable_find(network->NodeHashTable, id));
|
|
808
1003
|
}
|
|
809
1004
|
|
|
810
|
-
int findlink(Network *network, char *id)
|
|
1005
|
+
int findlink(Network *network, const char *id)
|
|
811
1006
|
/*----------------------------------------------------------------
|
|
812
1007
|
** Input: id = link ID
|
|
813
1008
|
** Output: none
|
|
@@ -823,7 +1018,7 @@ int findtank(Network *network, int index)
|
|
|
823
1018
|
/*----------------------------------------------------------------
|
|
824
1019
|
** Input: index = node index
|
|
825
1020
|
** Output: none
|
|
826
|
-
** Returns: index of tank with given node
|
|
1021
|
+
** Returns: index of tank with given node index, or NOTFOUND if tank not found
|
|
827
1022
|
** Purpose: for use in the deletenode function
|
|
828
1023
|
**----------------------------------------------------------------
|
|
829
1024
|
*/
|
|
@@ -840,7 +1035,7 @@ int findpump(Network *network, int index)
|
|
|
840
1035
|
/*----------------------------------------------------------------
|
|
841
1036
|
** Input: index = link ID
|
|
842
1037
|
** Output: none
|
|
843
|
-
** Returns: index of pump with given link
|
|
1038
|
+
** Returns: index of pump with given link index, or NOTFOUND if pump not found
|
|
844
1039
|
** Purpose: for use in the deletelink function
|
|
845
1040
|
**----------------------------------------------------------------
|
|
846
1041
|
*/
|
|
@@ -857,7 +1052,7 @@ int findvalve(Network *network, int index)
|
|
|
857
1052
|
/*----------------------------------------------------------------
|
|
858
1053
|
** Input: index = link ID
|
|
859
1054
|
** Output: none
|
|
860
|
-
** Returns: index of valve with given link
|
|
1055
|
+
** Returns: index of valve with given link index, or NOTFOUND if valve not found
|
|
861
1056
|
** Purpose: for use in the deletelink function
|
|
862
1057
|
**----------------------------------------------------------------
|
|
863
1058
|
*/
|
|
@@ -870,7 +1065,7 @@ int findvalve(Network *network, int index)
|
|
|
870
1065
|
return NOTFOUND;
|
|
871
1066
|
}
|
|
872
1067
|
|
|
873
|
-
int findpattern(Network *network, char *id)
|
|
1068
|
+
int findpattern(Network *network, const char *id)
|
|
874
1069
|
/*----------------------------------------------------------------
|
|
875
1070
|
** Input: id = time pattern ID
|
|
876
1071
|
** Output: none
|
|
@@ -889,7 +1084,7 @@ int findpattern(Network *network, char *id)
|
|
|
889
1084
|
return -1;
|
|
890
1085
|
}
|
|
891
1086
|
|
|
892
|
-
int findcurve(Network *network, char *id)
|
|
1087
|
+
int findcurve(Network *network, const char *id)
|
|
893
1088
|
/*----------------------------------------------------------------
|
|
894
1089
|
** Input: id = data curve ID
|
|
895
1090
|
** Output: none
|
|
@@ -912,8 +1107,8 @@ void adjustpattern(int *pat, int index)
|
|
|
912
1107
|
**----------------------------------------------------------------
|
|
913
1108
|
*/
|
|
914
1109
|
{
|
|
915
|
-
|
|
916
|
-
|
|
1110
|
+
if (*pat == index) *pat = 0;
|
|
1111
|
+
else if (*pat > index) (*pat)--;
|
|
917
1112
|
}
|
|
918
1113
|
|
|
919
1114
|
void adjustpatterns(Network *network, int index)
|
|
@@ -973,7 +1168,7 @@ void adjustcurves(Network *network, int index)
|
|
|
973
1168
|
**----------------------------------------------------------------
|
|
974
1169
|
*/
|
|
975
1170
|
{
|
|
976
|
-
int j, k,
|
|
1171
|
+
int j, k, curve;
|
|
977
1172
|
|
|
978
1173
|
// Adjust tank volume curves
|
|
979
1174
|
for (j = 1; j <= network->Ntanks; j++)
|
|
@@ -988,60 +1183,29 @@ void adjustcurves(Network *network, int index)
|
|
|
988
1183
|
adjustcurve(&network->Pump[j].Ecurve, index);
|
|
989
1184
|
}
|
|
990
1185
|
|
|
991
|
-
// Adjust GPV curves
|
|
1186
|
+
// Adjust PCV & GPV curves
|
|
992
1187
|
for (j = 1; j <= network->Nvalves; j++)
|
|
993
1188
|
{
|
|
994
1189
|
k = network->Valve[j].Link;
|
|
995
|
-
if (network->Link[k].Type ==
|
|
996
|
-
{
|
|
997
|
-
setting = INT(network->Link[k].Kc);
|
|
998
|
-
adjustcurve(&setting, index);
|
|
999
|
-
network->Link[k].Kc = setting;
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
int adjustpumpparams(Project *pr, int curveIndex)
|
|
1005
|
-
/*----------------------------------------------------------------
|
|
1006
|
-
** Input: curveIndex = index of a data curve
|
|
1007
|
-
** Output: returns an error code
|
|
1008
|
-
** Purpose: updates head curve parameters for pumps using a
|
|
1009
|
-
** curve whose data have been modified.
|
|
1010
|
-
**----------------------------------------------------------------
|
|
1011
|
-
*/
|
|
1012
|
-
{
|
|
1013
|
-
Network *network = &pr->network;
|
|
1014
|
-
|
|
1015
|
-
double *Ucf = pr->Ucf;
|
|
1016
|
-
int j, err = 0;
|
|
1017
|
-
Spump *pump;
|
|
1018
|
-
|
|
1019
|
-
// Check each pump
|
|
1020
|
-
for (j = 1; j <= network->Npumps; j++)
|
|
1021
|
-
{
|
|
1022
|
-
// Pump uses curve as head curve
|
|
1023
|
-
pump = &network->Pump[j];
|
|
1024
|
-
if ( curveIndex == pump->Hcurve)
|
|
1190
|
+
if (network->Link[k].Type == PCV)
|
|
1025
1191
|
{
|
|
1026
|
-
|
|
1027
|
-
pump->Ptype = NOCURVE;
|
|
1028
|
-
err = updatepumpparams(pr, curveIndex);
|
|
1029
|
-
if (err > 0) break;
|
|
1030
|
-
|
|
1031
|
-
// Convert parameters to internal units
|
|
1032
|
-
if (pump->Ptype == POWER_FUNC)
|
|
1192
|
+
if ((curve = network->Valve[j].Curve) > 0)
|
|
1033
1193
|
{
|
|
1034
|
-
|
|
1035
|
-
|
|
1194
|
+
adjustcurve(&curve, index);
|
|
1195
|
+
network->Valve[j].Curve = curve;
|
|
1196
|
+
if (curve == 0)
|
|
1197
|
+
network->Link[k].Kc = 0.0;
|
|
1036
1198
|
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1199
|
+
}
|
|
1200
|
+
if (network->Link[k].Type == GPV)
|
|
1201
|
+
{
|
|
1202
|
+
curve = INT(network->Link[k].Kc);
|
|
1203
|
+
adjustcurve(&curve, index);
|
|
1204
|
+
network->Link[k].Kc = curve;
|
|
1040
1205
|
}
|
|
1041
1206
|
}
|
|
1042
|
-
return err;
|
|
1043
1207
|
}
|
|
1044
|
-
|
|
1208
|
+
|
|
1045
1209
|
|
|
1046
1210
|
int resizecurve(Scurve *curve, int size)
|
|
1047
1211
|
/*----------------------------------------------------------------
|
|
@@ -1072,6 +1236,112 @@ int resizecurve(Scurve *curve, int size)
|
|
|
1072
1236
|
return 0;
|
|
1073
1237
|
}
|
|
1074
1238
|
|
|
1239
|
+
|
|
1240
|
+
int setcontrol(EN_Project p, int type, int linkIndex, double setting,
|
|
1241
|
+
int nodeIndex, double level, Scontrol *control)
|
|
1242
|
+
/*----------------------------------------------------------------
|
|
1243
|
+
** Input: type = type of control (see EN_ControlType)
|
|
1244
|
+
** linkIndex = index of link being controlled
|
|
1245
|
+
** setting = link control setting (e.g., pump speed)
|
|
1246
|
+
** nodeIndex = index of node controlling a link (for level controls)
|
|
1247
|
+
** level = control activation level (pressure for junction nodes,
|
|
1248
|
+
** water level for tank nodes or time value for time-based
|
|
1249
|
+
** control)
|
|
1250
|
+
** Output: control = control struct whose properties are being set
|
|
1251
|
+
** Returns: error code
|
|
1252
|
+
** Purpose: assigns properties to a control struct.
|
|
1253
|
+
**----------------------------------------------------------------
|
|
1254
|
+
*/
|
|
1255
|
+
{
|
|
1256
|
+
Network *net = &p->network;
|
|
1257
|
+
Parser *parser = &p->parser;
|
|
1258
|
+
|
|
1259
|
+
long t = 0;
|
|
1260
|
+
double lvl = 0.0, s = MISSING;
|
|
1261
|
+
double *Ucf = p->Ucf;
|
|
1262
|
+
LinkType linktype;
|
|
1263
|
+
StatusType status = ACTIVE;
|
|
1264
|
+
|
|
1265
|
+
// Cannot control check valve
|
|
1266
|
+
linktype = net->Link[linkIndex].Type;
|
|
1267
|
+
if (linktype == CVPIPE) return 207;
|
|
1268
|
+
|
|
1269
|
+
// Check for valid control type and node index
|
|
1270
|
+
if (type < 0 || type > TIMEOFDAY) return 251;
|
|
1271
|
+
if (type == LOWLEVEL || type == HILEVEL)
|
|
1272
|
+
{
|
|
1273
|
+
if (nodeIndex < 1 || nodeIndex > net->Nnodes) return 203;
|
|
1274
|
+
}
|
|
1275
|
+
else nodeIndex = 0;
|
|
1276
|
+
|
|
1277
|
+
// Check if control setting is a status level
|
|
1278
|
+
if (setting == SET_OPEN)
|
|
1279
|
+
{
|
|
1280
|
+
status = OPEN;
|
|
1281
|
+
if (linktype == PUMP) s = 1.0;
|
|
1282
|
+
if (linktype == GPV) s = net->Link[linkIndex].Kc;
|
|
1283
|
+
}
|
|
1284
|
+
else if (setting == SET_CLOSED)
|
|
1285
|
+
{
|
|
1286
|
+
status = CLOSED;
|
|
1287
|
+
if (linktype == PUMP) s = 0.0;
|
|
1288
|
+
if (linktype == GPV) s = net->Link[linkIndex].Kc;
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
// Convert units of control setting
|
|
1292
|
+
else
|
|
1293
|
+
{
|
|
1294
|
+
s = setting;
|
|
1295
|
+
switch (linktype)
|
|
1296
|
+
{
|
|
1297
|
+
case PIPE:
|
|
1298
|
+
case PUMP:
|
|
1299
|
+
if (s < 0.0) return 202;
|
|
1300
|
+
else if (s == 0.0) status = CLOSED;
|
|
1301
|
+
else status = OPEN;
|
|
1302
|
+
break;
|
|
1303
|
+
case PRV:
|
|
1304
|
+
case PSV:
|
|
1305
|
+
case PBV:
|
|
1306
|
+
s /= Ucf[PRESSURE];
|
|
1307
|
+
break;
|
|
1308
|
+
case FCV:
|
|
1309
|
+
s /= Ucf[FLOW];
|
|
1310
|
+
break;
|
|
1311
|
+
case GPV:
|
|
1312
|
+
if (s == 0.0) status = CLOSED;
|
|
1313
|
+
else if (s == 1.0) status = OPEN;
|
|
1314
|
+
else return 202;
|
|
1315
|
+
s = net->Link[linkIndex].Kc;
|
|
1316
|
+
break;
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
// Determine if control level is a pressure, tank level or time value
|
|
1321
|
+
if (type == LOWLEVEL || type == HILEVEL)
|
|
1322
|
+
{
|
|
1323
|
+
if (nodeIndex > net->Njuncs) lvl = net->Node[nodeIndex].El + level / Ucf[ELEV];
|
|
1324
|
+
else lvl = net->Node[nodeIndex].El + level / Ucf[PRESSURE];
|
|
1325
|
+
}
|
|
1326
|
+
else if (type == TIMER || type == TIMEOFDAY)
|
|
1327
|
+
{
|
|
1328
|
+
t = (long)level;
|
|
1329
|
+
if (t < 0) return 202;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
// Assign values to control struct
|
|
1333
|
+
control->Link = linkIndex;
|
|
1334
|
+
control->Node = nodeIndex;
|
|
1335
|
+
control->Type = type;
|
|
1336
|
+
control->Status = status;
|
|
1337
|
+
control->Setting = s;
|
|
1338
|
+
control->Time = t;
|
|
1339
|
+
control->Grade = lvl;
|
|
1340
|
+
control->isEnabled = TRUE;
|
|
1341
|
+
return 0;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
|
|
1075
1345
|
int getcomment(Network *network, int object, int index, char *comment)
|
|
1076
1346
|
//----------------------------------------------------------------
|
|
1077
1347
|
// Input: object = a type of network object
|
|
@@ -1154,6 +1424,67 @@ int setcomment(Network *network, int object, int index, const char *newcomment)
|
|
|
1154
1424
|
}
|
|
1155
1425
|
}
|
|
1156
1426
|
|
|
1427
|
+
int gettag(Network *network, int object, int index, char *tag)
|
|
1428
|
+
//----------------------------------------------------------------
|
|
1429
|
+
// Input: object = a type of network object
|
|
1430
|
+
// index = index of the specified object
|
|
1431
|
+
// tag = the object's tag string
|
|
1432
|
+
// Output: error code
|
|
1433
|
+
// Purpose: gets the tag string assigned to an object.
|
|
1434
|
+
//----------------------------------------------------------------
|
|
1435
|
+
{
|
|
1436
|
+
char *currenttag;
|
|
1437
|
+
|
|
1438
|
+
// Get pointer to specified object's tag
|
|
1439
|
+
switch (object)
|
|
1440
|
+
{
|
|
1441
|
+
case NODE:
|
|
1442
|
+
if (index < 1 || index > network->Nnodes) return 251;
|
|
1443
|
+
currenttag = network->Node[index].Tag;
|
|
1444
|
+
break;
|
|
1445
|
+
case LINK:
|
|
1446
|
+
if (index < 1 || index > network->Nlinks) return 251;
|
|
1447
|
+
currenttag = network->Link[index].Tag;
|
|
1448
|
+
break;
|
|
1449
|
+
default:
|
|
1450
|
+
strcpy(tag, "");
|
|
1451
|
+
return 251;
|
|
1452
|
+
}
|
|
1453
|
+
// Copy the object's tag to the returned string
|
|
1454
|
+
if (currenttag) strcpy(tag, currenttag);
|
|
1455
|
+
else tag[0] = '\0';
|
|
1456
|
+
return 0;
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
int settag(Network *network, int object, int index, const char *newtag)
|
|
1460
|
+
//----------------------------------------------------------------
|
|
1461
|
+
// Input: object = a type of network object
|
|
1462
|
+
// index = index of the specified object
|
|
1463
|
+
// newtag = new tag string
|
|
1464
|
+
// Output: error code
|
|
1465
|
+
// Purpose: sets the tag string of an object.
|
|
1466
|
+
//----------------------------------------------------------------
|
|
1467
|
+
{
|
|
1468
|
+
char *tag;
|
|
1469
|
+
|
|
1470
|
+
switch (object)
|
|
1471
|
+
{
|
|
1472
|
+
case NODE:
|
|
1473
|
+
if (index < 1 || index > network->Nnodes) return 251;
|
|
1474
|
+
tag = network->Node[index].Tag;
|
|
1475
|
+
network->Node[index].Tag = xstrcpy(&tag, newtag, MAXMSG);
|
|
1476
|
+
return 0;
|
|
1477
|
+
|
|
1478
|
+
case LINK:
|
|
1479
|
+
if (index < 1 || index > network->Nlinks) return 251;
|
|
1480
|
+
tag = network->Link[index].Tag;
|
|
1481
|
+
network->Link[index].Tag = xstrcpy(&tag, newtag, MAXMSG);
|
|
1482
|
+
return 0;
|
|
1483
|
+
|
|
1484
|
+
default: return 251;
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1157
1488
|
int namevalid(const char *name)
|
|
1158
1489
|
//----------------------------------------------------------------
|
|
1159
1490
|
// Input: name = name used to ID an object
|
|
@@ -1219,10 +1550,10 @@ char *xstrcpy(char **s1, const char *s2, const size_t n)
|
|
|
1219
1550
|
// s1 points to a valid memory location or is NULL. E.g.,
|
|
1220
1551
|
// the following code will likely cause a segment fault:
|
|
1221
1552
|
// char *s;
|
|
1222
|
-
// s = xstrcpy(s, "Some text");
|
|
1553
|
+
// s = xstrcpy(&s, "Some text");
|
|
1223
1554
|
// while this would work correctly:
|
|
1224
1555
|
// char *s = NULL;
|
|
1225
|
-
// s = xstrcpy(s, "Some text");
|
|
1556
|
+
// s = xstrcpy(&s, "Some text");
|
|
1226
1557
|
//----------------------------------------------------------------
|
|
1227
1558
|
{
|
|
1228
1559
|
size_t n1 = 0, n2 = 0;
|
|
@@ -1244,7 +1575,7 @@ char *xstrcpy(char **s1, const char *s2, const size_t n)
|
|
|
1244
1575
|
if (n2 > n1) *s1 = realloc(*s1, (n2 + 1) * sizeof(char));
|
|
1245
1576
|
|
|
1246
1577
|
// Copy the source string into the destination string
|
|
1247
|
-
strncpy(*s1, s2, n2+1);
|
|
1578
|
+
if (*s1) strncpy(*s1, s2, n2+1);
|
|
1248
1579
|
return *s1;
|
|
1249
1580
|
}
|
|
1250
1581
|
|
|
@@ -1283,6 +1614,7 @@ double interp(int n, double x[], double y[], double xx)
|
|
|
1283
1614
|
int k, m;
|
|
1284
1615
|
double dx, dy;
|
|
1285
1616
|
|
|
1617
|
+
if (n == 0) return 0.0;
|
|
1286
1618
|
m = n - 1; // Highest data index
|
|
1287
1619
|
if (xx <= x[0]) return (y[0]); // xx off low end of curve
|
|
1288
1620
|
for (k = 1; k <= m; k++) // Bracket xx on curve
|