epyt-flow 0.14.1__py3-none-any.whl → 0.14.2__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 +8 -40
- epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +3 -3
- epyt_flow/EPANET/EPANET/SRC_engines/Readme_SRC_Engines.txt +18 -0
- epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +7 -24
- epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +374 -726
- epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +32 -128
- epyt_flow/EPANET/EPANET/SRC_engines/epanet2.def +131 -0
- epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +1 -7
- epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +14 -40
- 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 +40 -192
- epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +46 -101
- epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +24 -85
- epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +63 -29
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +37 -70
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +234 -408
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +37 -87
- epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +79 -153
- epyt_flow/EPANET/EPANET/SRC_engines/input1.c +94 -59
- epyt_flow/EPANET/EPANET/SRC_engines/input2.c +202 -73
- epyt_flow/EPANET/EPANET/SRC_engines/input3.c +351 -446
- epyt_flow/EPANET/EPANET/SRC_engines/main.c +93 -0
- epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +4 -8
- epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +23 -23
- epyt_flow/EPANET/EPANET/SRC_engines/output.c +4 -5
- epyt_flow/EPANET/EPANET/SRC_engines/project.c +75 -407
- epyt_flow/EPANET/EPANET/SRC_engines/quality.c +2 -12
- epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +13 -70
- epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +5 -7
- epyt_flow/EPANET/EPANET/SRC_engines/report.c +20 -88
- epyt_flow/EPANET/EPANET/SRC_engines/rules.c +6 -144
- epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +19 -19
- epyt_flow/EPANET/EPANET/SRC_engines/text.h +5 -16
- epyt_flow/EPANET/EPANET/SRC_engines/types.h +19 -73
- epyt_flow/EPANET/compile_linux.sh +1 -1
- epyt_flow/EPANET/compile_macos.sh +1 -1
- epyt_flow/VERSION +1 -1
- epyt_flow/simulation/scada/scada_data.py +1 -1
- epyt_flow/utils.py +66 -0
- epyt_flow/visualization/visualization_utils.py +4 -2
- {epyt_flow-0.14.1.dist-info → epyt_flow-0.14.2.dist-info}/METADATA +1 -1
- {epyt_flow-0.14.1.dist-info → epyt_flow-0.14.2.dist-info}/RECORD +46 -52
- epyt_flow/EPANET/EPANET/SRC_engines/flowbalance.c +0 -186
- epyt_flow/EPANET/EPANET/SRC_engines/leakage.c +0 -527
- epyt_flow/EPANET/EPANET/SRC_engines/util/cstr_helper.c +0 -59
- epyt_flow/EPANET/EPANET/SRC_engines/util/cstr_helper.h +0 -38
- epyt_flow/EPANET/EPANET/SRC_engines/util/errormanager.c +0 -92
- epyt_flow/EPANET/EPANET/SRC_engines/util/errormanager.h +0 -39
- epyt_flow/EPANET/EPANET/SRC_engines/util/filemanager.c +0 -212
- epyt_flow/EPANET/EPANET/SRC_engines/util/filemanager.h +0 -81
- epyt_flow/EPANET/EPANET/SRC_engines/validate.c +0 -408
- {epyt_flow-0.14.1.dist-info → epyt_flow-0.14.2.dist-info}/WHEEL +0 -0
- {epyt_flow-0.14.1.dist-info → epyt_flow-0.14.2.dist-info}/licenses/LICENSE +0 -0
- {epyt_flow-0.14.1.dist-info → epyt_flow-0.14.2.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.2
|
|
5
5
|
Module: epanet.c
|
|
6
6
|
Description: implementation of EPANET's API functions
|
|
7
7
|
Authors: see AUTHORS
|
|
8
8
|
Copyright: see AUTHORS
|
|
9
9
|
License: see LICENSE
|
|
10
|
-
Last Updated:
|
|
10
|
+
Last Updated: 11/15/2019
|
|
11
11
|
******************************************************************************
|
|
12
12
|
*/
|
|
13
13
|
|
|
@@ -143,7 +143,7 @@ int DLLEXPORT EN_init(EN_Project p, const char *rptFile, const char *outFile,
|
|
|
143
143
|
p->report.Rptflag = 1;
|
|
144
144
|
|
|
145
145
|
// Check for valid arguments
|
|
146
|
-
if (unitsType < 0 || unitsType >
|
|
146
|
+
if (unitsType < 0 || unitsType > CMD) return 251;
|
|
147
147
|
if (headLossType < 0 || headLossType > CM) return 251;
|
|
148
148
|
|
|
149
149
|
// Open files
|
|
@@ -179,29 +179,61 @@ int DLLEXPORT EN_open(EN_Project p, const char *inpFile, const char *rptFile,
|
|
|
179
179
|
** outFile = name of binary output file
|
|
180
180
|
** Output: none
|
|
181
181
|
** Returns: error code
|
|
182
|
-
** Purpose:
|
|
183
|
-
**----------------------------------------------------------------
|
|
184
|
-
*/
|
|
185
|
-
{
|
|
186
|
-
writewin(p->viewprog, FMT100);
|
|
187
|
-
return openproject(p, inpFile, rptFile, outFile, FALSE);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
int DLLEXPORT EN_openX(EN_Project p, const char *inpFile,
|
|
191
|
-
const char *rptFile, const char *outFile)
|
|
192
|
-
/*----------------------------------------------------------------
|
|
193
|
-
** Input: inpFile = name of input file
|
|
194
|
-
** rptFile = name of report file
|
|
195
|
-
** outFile = name of binary output file
|
|
196
|
-
** Output: none
|
|
197
|
-
** Returns: error code
|
|
198
|
-
** Purpose: reads an EPANET input file with errors allowed.
|
|
182
|
+
** Purpose: opens an EPANET input file & reads in network data
|
|
199
183
|
**----------------------------------------------------------------
|
|
200
184
|
*/
|
|
201
185
|
{
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
186
|
+
int errcode = 0;
|
|
187
|
+
|
|
188
|
+
// Set system flags
|
|
189
|
+
p->Openflag = FALSE;
|
|
190
|
+
p->hydraul.OpenHflag = FALSE;
|
|
191
|
+
p->quality.OpenQflag = FALSE;
|
|
192
|
+
p->outfile.SaveHflag = FALSE;
|
|
193
|
+
p->outfile.SaveQflag = FALSE;
|
|
194
|
+
p->Warnflag = FALSE;
|
|
195
|
+
p->report.Messageflag = TRUE;
|
|
196
|
+
p->report.Rptflag = 1;
|
|
197
|
+
|
|
198
|
+
// Initialize data arrays to NULL
|
|
199
|
+
initpointers(p);
|
|
200
|
+
|
|
201
|
+
// Open input & report files
|
|
202
|
+
ERRCODE(openfiles(p, inpFile, rptFile, outFile));
|
|
203
|
+
if (errcode > 0)
|
|
204
|
+
{
|
|
205
|
+
errmsg(p, errcode);
|
|
206
|
+
return errcode;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Allocate memory for project's data arrays
|
|
210
|
+
writewin(p->viewprog, FMT100);
|
|
211
|
+
ERRCODE(netsize(p));
|
|
212
|
+
ERRCODE(allocdata(p));
|
|
213
|
+
|
|
214
|
+
// Read input data
|
|
215
|
+
ERRCODE(getdata(p));
|
|
216
|
+
|
|
217
|
+
// Close input file
|
|
218
|
+
if (p->parser.InFile != NULL)
|
|
219
|
+
{
|
|
220
|
+
fclose(p->parser.InFile);
|
|
221
|
+
p->parser.InFile = NULL;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// If using previously saved hydraulics file then open it
|
|
225
|
+
if (p->outfile.Hydflag == USE) ERRCODE(openhydfile(p));
|
|
226
|
+
|
|
227
|
+
// Write input summary to report file
|
|
228
|
+
if (!errcode)
|
|
229
|
+
{
|
|
230
|
+
if (p->report.Summaryflag) writesummary(p);
|
|
231
|
+
writetime(p, FMT104);
|
|
232
|
+
p->Openflag = TRUE;
|
|
233
|
+
}
|
|
234
|
+
else errmsg(p, errcode);
|
|
235
|
+
return errcode;
|
|
236
|
+
}
|
|
205
237
|
|
|
206
238
|
int DLLEXPORT EN_gettitle(EN_Project p, char *line1, char *line2, char *line3)
|
|
207
239
|
/*----------------------------------------------------------------
|
|
@@ -219,8 +251,7 @@ int DLLEXPORT EN_gettitle(EN_Project p, char *line1, char *line2, char *line3)
|
|
|
219
251
|
return 0;
|
|
220
252
|
}
|
|
221
253
|
|
|
222
|
-
int DLLEXPORT EN_settitle(EN_Project p,
|
|
223
|
-
const char *line2, const char *line3)
|
|
254
|
+
int DLLEXPORT EN_settitle(EN_Project p, char *line1, char *line2, char *line3)
|
|
224
255
|
/*----------------------------------------------------------------
|
|
225
256
|
** Input: line1, line2, line3 = project's title lines
|
|
226
257
|
** Returns: error code
|
|
@@ -248,8 +279,7 @@ int DLLEXPORT EN_getcomment(EN_Project p, int object, int index, char *comment)
|
|
|
248
279
|
return getcomment(&p->network, object, index, comment);
|
|
249
280
|
}
|
|
250
281
|
|
|
251
|
-
int DLLEXPORT EN_setcomment(EN_Project p, int object, int index,
|
|
252
|
-
const char *comment)
|
|
282
|
+
int DLLEXPORT EN_setcomment(EN_Project p, int object, int index, char *comment)
|
|
253
283
|
/*----------------------------------------------------------------
|
|
254
284
|
** Input: object = a type of object (see EN_ObjectType)
|
|
255
285
|
** index = the object's index
|
|
@@ -262,32 +292,6 @@ int DLLEXPORT EN_setcomment(EN_Project p, int object, int index,
|
|
|
262
292
|
return setcomment(&p->network, object, index, comment);
|
|
263
293
|
}
|
|
264
294
|
|
|
265
|
-
int DLLEXPORT EN_gettag(EN_Project p, int object, int index, char *tag)
|
|
266
|
-
/*----------------------------------------------------------------
|
|
267
|
-
** Input: object = either EN_NODE or EN_LINK
|
|
268
|
-
** index = the object's index
|
|
269
|
-
** Output: tag = the tag string assigned to the object
|
|
270
|
-
** Returns: error code
|
|
271
|
-
** Purpose: Retrieves an object's tag string
|
|
272
|
-
**----------------------------------------------------------------
|
|
273
|
-
*/
|
|
274
|
-
{
|
|
275
|
-
return gettag(&p->network, object, index, tag);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
int DLLEXPORT EN_settag(EN_Project p, int object, int index,
|
|
279
|
-
const char *tag)
|
|
280
|
-
/*----------------------------------------------------------------
|
|
281
|
-
** Input: object = either EN_NODE or EN_LINK
|
|
282
|
-
** index = the object's index
|
|
283
|
-
** tag = a descriptive comment to assign
|
|
284
|
-
** Returns: error code
|
|
285
|
-
** Purpose: Assigns a tag string to an object
|
|
286
|
-
**----------------------------------------------------------------
|
|
287
|
-
*/
|
|
288
|
-
{
|
|
289
|
-
return settag(&p->network, object, index, tag);
|
|
290
|
-
}
|
|
291
295
|
int DLLEXPORT EN_getcount(EN_Project p, int object, int *count)
|
|
292
296
|
/*----------------------------------------------------------------
|
|
293
297
|
** Input: object = type of object to count (see EN_CountType)
|
|
@@ -353,6 +357,7 @@ int DLLEXPORT EN_close(EN_Project p)
|
|
|
353
357
|
*/
|
|
354
358
|
{
|
|
355
359
|
// Free all project data
|
|
360
|
+
if (p->Openflag) writetime(p, FMT105);
|
|
356
361
|
freedata(p);
|
|
357
362
|
|
|
358
363
|
// Close output file
|
|
@@ -488,11 +493,7 @@ int DLLEXPORT EN_openH(EN_Project p)
|
|
|
488
493
|
|
|
489
494
|
// Open hydraulics solver
|
|
490
495
|
ERRCODE(openhyd(p));
|
|
491
|
-
if (!errcode)
|
|
492
|
-
{
|
|
493
|
-
p->hydraul.OpenHflag = TRUE;
|
|
494
|
-
writetime(p, FMT104);
|
|
495
|
-
}
|
|
496
|
+
if (!errcode) p->hydraul.OpenHflag = TRUE;
|
|
496
497
|
else errmsg(p, errcode);
|
|
497
498
|
return errcode;
|
|
498
499
|
}
|
|
@@ -535,10 +536,6 @@ int DLLEXPORT EN_initH(EN_Project p, int initFlag)
|
|
|
535
536
|
return errcode;
|
|
536
537
|
}
|
|
537
538
|
}
|
|
538
|
-
|
|
539
|
-
// Open pipe leakage modeling system
|
|
540
|
-
errcode = openleakage(p);
|
|
541
|
-
if (errcode) return errcode;
|
|
542
539
|
|
|
543
540
|
// Initialize hydraulics solver
|
|
544
541
|
inithyd(p, fflag);
|
|
@@ -593,11 +590,7 @@ int DLLEXPORT EN_closeH(EN_Project p)
|
|
|
593
590
|
*/
|
|
594
591
|
{
|
|
595
592
|
if (!p->Openflag) return 102;
|
|
596
|
-
if (p->hydraul.OpenHflag)
|
|
597
|
-
{
|
|
598
|
-
closeleakage(p);
|
|
599
|
-
closehyd(p);
|
|
600
|
-
}
|
|
593
|
+
if (p->hydraul.OpenHflag) closehyd(p);
|
|
601
594
|
p->hydraul.OpenHflag = FALSE;
|
|
602
595
|
return 0;
|
|
603
596
|
}
|
|
@@ -839,7 +832,6 @@ int DLLEXPORT EN_closeQ(EN_Project p)
|
|
|
839
832
|
closequal(p);
|
|
840
833
|
p->quality.OpenQflag = FALSE;
|
|
841
834
|
closeoutfile(p);
|
|
842
|
-
writetime(p, FMT105);
|
|
843
835
|
return 0;
|
|
844
836
|
}
|
|
845
837
|
|
|
@@ -849,35 +841,7 @@ int DLLEXPORT EN_closeQ(EN_Project p)
|
|
|
849
841
|
|
|
850
842
|
********************************************************************/
|
|
851
843
|
|
|
852
|
-
|
|
853
|
-
int DLLEXPORT EN_setreportcallback(EN_Project p, void (*callback)(void*,void*,const char*))
|
|
854
|
-
/*----------------------------------------------------------------
|
|
855
|
-
** Input: callback = a pointer to a reporting function
|
|
856
|
-
** Output: none
|
|
857
|
-
** Returns: error code
|
|
858
|
-
** Purpose: replaces EPANET's normal use of a designated report file
|
|
859
|
-
**----------------------------------------------------------------
|
|
860
|
-
*/
|
|
861
|
-
{
|
|
862
|
-
p->report.reportCallback = callback;
|
|
863
|
-
return 0;
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
int DLLEXPORT EN_setreportcallbackuserdata(EN_Project p, void *userData)
|
|
867
|
-
/*----------------------------------------------------------------
|
|
868
|
-
** Input: userData = a pointer to a client-side data object
|
|
869
|
-
** Output: none
|
|
870
|
-
** Returns: error code
|
|
871
|
-
** Purpose: sets the client-side data object used in conjunction with
|
|
872
|
-
** the callback function in EN_setreportcallback
|
|
873
|
-
**----------------------------------------------------------------
|
|
874
|
-
*/
|
|
875
|
-
{
|
|
876
|
-
p->report.reportCallbackUserData = userData;
|
|
877
|
-
return 0;
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
int DLLEXPORT EN_writeline(EN_Project p, const char *line)
|
|
844
|
+
int DLLEXPORT EN_writeline(EN_Project p, char *line)
|
|
881
845
|
/*----------------------------------------------------------------
|
|
882
846
|
** Input: line = line of text
|
|
883
847
|
** Output: none
|
|
@@ -913,7 +877,7 @@ int DLLEXPORT EN_report(EN_Project p)
|
|
|
913
877
|
return errcode;
|
|
914
878
|
}
|
|
915
879
|
|
|
916
|
-
int DLLEXPORT EN_copyreport(EN_Project p,
|
|
880
|
+
int DLLEXPORT EN_copyreport(EN_Project p, char *filename)
|
|
917
881
|
/*----------------------------------------------------------------
|
|
918
882
|
** Input: filename = name of file to receive copy of report
|
|
919
883
|
** Output: none
|
|
@@ -962,7 +926,7 @@ int DLLEXPORT EN_resetreport(EN_Project p)
|
|
|
962
926
|
return 0;
|
|
963
927
|
}
|
|
964
928
|
|
|
965
|
-
int DLLEXPORT EN_setreport(EN_Project p,
|
|
929
|
+
int DLLEXPORT EN_setreport(EN_Project p, char *format)
|
|
966
930
|
/*----------------------------------------------------------------
|
|
967
931
|
** Input: format = a report formatting command
|
|
968
932
|
** Output: none
|
|
@@ -1019,7 +983,7 @@ int DLLEXPORT EN_getversion(int *version)
|
|
|
1019
983
|
|
|
1020
984
|
int DLLEXPORT EN_geterror(int errcode, char *errmsg, int maxLen)
|
|
1021
985
|
/*----------------------------------------------------------------
|
|
1022
|
-
** Input: errcode = an error or
|
|
986
|
+
** Input: errcode = an error or warnng code
|
|
1023
987
|
** maxLen = maximum characters that errmsg can hold
|
|
1024
988
|
** Output: errmsg = text of error/warning message
|
|
1025
989
|
** Returns: error code
|
|
@@ -1092,9 +1056,6 @@ int DLLEXPORT EN_getstatistic(EN_Project p, int type, double *value)
|
|
|
1092
1056
|
case EN_DEMANDREDUCTION:
|
|
1093
1057
|
*value = p->hydraul.DemandReduction;
|
|
1094
1058
|
break;
|
|
1095
|
-
case EN_LEAKAGELOSS:
|
|
1096
|
-
*value = p->hydraul.LeakageLoss;
|
|
1097
|
-
break;
|
|
1098
1059
|
case EN_MASSBALANCE:
|
|
1099
1060
|
*value = p->quality.MassBalance.ratio;
|
|
1100
1061
|
break;
|
|
@@ -1226,18 +1187,7 @@ int DLLEXPORT EN_getoption(EN_Project p, int option, double *value)
|
|
|
1226
1187
|
case EN_CONCENLIMIT:
|
|
1227
1188
|
v = qual->Climit * p->Ucf[QUALITY];
|
|
1228
1189
|
break;
|
|
1229
|
-
|
|
1230
|
-
v = hyd->DefPat;
|
|
1231
|
-
break;
|
|
1232
|
-
case EN_EMITBACKFLOW:
|
|
1233
|
-
v = hyd->EmitBackFlag;
|
|
1234
|
-
break;
|
|
1235
|
-
case EN_PRESS_UNITS:
|
|
1236
|
-
v = (double)p->parser.Pressflag;
|
|
1237
|
-
break;
|
|
1238
|
-
case EN_STATUS_REPORT:
|
|
1239
|
-
v = (double)( p->report.Statflag);
|
|
1240
|
-
break;
|
|
1190
|
+
|
|
1241
1191
|
default:
|
|
1242
1192
|
return 251;
|
|
1243
1193
|
}
|
|
@@ -1261,12 +1211,9 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
|
|
|
1261
1211
|
|
|
1262
1212
|
int Njuncs = net->Njuncs;
|
|
1263
1213
|
double *Ucf = p->Ucf;
|
|
1264
|
-
int i, j, pat
|
|
1214
|
+
int i, j, pat;
|
|
1265
1215
|
double Ke, n, ucf;
|
|
1266
1216
|
|
|
1267
|
-
double qfactor, hfactor, pfactor, dfactor;
|
|
1268
|
-
double dcf, pcf, hcf, qcf;
|
|
1269
|
-
|
|
1270
1217
|
if (!p->Openflag) return 102;
|
|
1271
1218
|
|
|
1272
1219
|
// The EN_UNBALANCED option can be < 0 indicating that the simulation
|
|
@@ -1283,7 +1230,7 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
|
|
|
1283
1230
|
// All other option values must be non-negative
|
|
1284
1231
|
if (value < 0.0) return 213;
|
|
1285
1232
|
|
|
1286
|
-
// Process the
|
|
1233
|
+
// Process the speficied option
|
|
1287
1234
|
switch (option)
|
|
1288
1235
|
{
|
|
1289
1236
|
case EN_TRIALS:
|
|
@@ -1355,12 +1302,7 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
|
|
|
1355
1302
|
|
|
1356
1303
|
case EN_SP_GRAVITY:
|
|
1357
1304
|
if (value <= 0.0) return 213;
|
|
1358
|
-
|
|
1359
|
-
p->parser.Pressflag == KPA ||
|
|
1360
|
-
p->parser.Pressflag == BAR)
|
|
1361
|
-
{
|
|
1362
|
-
Ucf[PRESSURE] *= (value / hyd->SpGrav);
|
|
1363
|
-
}
|
|
1305
|
+
Ucf[PRESSURE] *= (value / hyd->SpGrav);
|
|
1364
1306
|
hyd->SpGrav = value;
|
|
1365
1307
|
break;
|
|
1366
1308
|
|
|
@@ -1402,42 +1344,6 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
|
|
|
1402
1344
|
qual->Climit = value / p->Ucf[QUALITY];
|
|
1403
1345
|
break;
|
|
1404
1346
|
|
|
1405
|
-
case EN_DEMANDPATTERN:
|
|
1406
|
-
pat = ROUND(value);
|
|
1407
|
-
if (pat < 0 || pat > net->Npats) return 205;
|
|
1408
|
-
hyd->DefPat = pat;
|
|
1409
|
-
break;
|
|
1410
|
-
|
|
1411
|
-
case EN_EMITBACKFLOW:
|
|
1412
|
-
if (value == 0.0 || value == 1.0) hyd->EmitBackFlag = (int)value;
|
|
1413
|
-
else return 213;
|
|
1414
|
-
break;
|
|
1415
|
-
|
|
1416
|
-
case EN_PRESS_UNITS:
|
|
1417
|
-
unit = ROUND(value);
|
|
1418
|
-
if (unit < 0 || unit > FEET) return 205;
|
|
1419
|
-
p->parser.Pressflag = unit;
|
|
1420
|
-
|
|
1421
|
-
dfactor = Ucf[DEMAND];
|
|
1422
|
-
pfactor = Ucf[PRESSURE];
|
|
1423
|
-
hfactor = Ucf[HEAD];
|
|
1424
|
-
qfactor = Ucf[FLOW];
|
|
1425
|
-
initunits(p);
|
|
1426
|
-
|
|
1427
|
-
// Update units in rules
|
|
1428
|
-
dcf = Ucf[DEMAND] / dfactor;
|
|
1429
|
-
pcf = Ucf[PRESSURE] / pfactor;
|
|
1430
|
-
hcf = Ucf[HEAD] / hfactor;
|
|
1431
|
-
qcf = Ucf[FLOW] / qfactor;
|
|
1432
|
-
updateruleunits(p, dcf, pcf, hcf, qcf);
|
|
1433
|
-
break;
|
|
1434
|
-
|
|
1435
|
-
case EN_STATUS_REPORT:
|
|
1436
|
-
i = ROUND(value);
|
|
1437
|
-
if (i < EN_NO_REPORT || i > EN_FULL_REPORT) return 213;
|
|
1438
|
-
p->report.Statflag = i;
|
|
1439
|
-
break;
|
|
1440
|
-
|
|
1441
1347
|
default:
|
|
1442
1348
|
return 251;
|
|
1443
1349
|
}
|
|
@@ -1470,9 +1376,8 @@ int DLLEXPORT EN_setflowunits(EN_Project p, int units)
|
|
|
1470
1376
|
{
|
|
1471
1377
|
Network *net = &p->network;
|
|
1472
1378
|
|
|
1473
|
-
int i, j
|
|
1474
|
-
double qfactor, vfactor, hfactor, efactor,
|
|
1475
|
-
double dcf, pcf, hcf, qcf;
|
|
1379
|
+
int i, j;
|
|
1380
|
+
double qfactor, vfactor, hfactor, efactor, xfactor, yfactor;
|
|
1476
1381
|
double *Ucf = p->Ucf;
|
|
1477
1382
|
|
|
1478
1383
|
if (!p->Openflag) return 102;
|
|
@@ -1482,10 +1387,7 @@ int DLLEXPORT EN_setflowunits(EN_Project p, int units)
|
|
|
1482
1387
|
vfactor = Ucf[VOLUME];
|
|
1483
1388
|
hfactor = Ucf[HEAD];
|
|
1484
1389
|
efactor = Ucf[ELEV];
|
|
1485
|
-
pfactor = Ucf[PRESSURE];
|
|
1486
|
-
dfactor = Ucf[DEMAND];
|
|
1487
1390
|
|
|
1488
|
-
oldUnitFlag = p->parser.Unitsflag;
|
|
1489
1391
|
p->parser.Flowflag = units;
|
|
1490
1392
|
switch (units)
|
|
1491
1393
|
{
|
|
@@ -1494,7 +1396,6 @@ int DLLEXPORT EN_setflowunits(EN_Project p, int units)
|
|
|
1494
1396
|
case MLD:
|
|
1495
1397
|
case CMH:
|
|
1496
1398
|
case CMD:
|
|
1497
|
-
case CMS:
|
|
1498
1399
|
p->parser.Unitsflag = SI;
|
|
1499
1400
|
break;
|
|
1500
1401
|
default:
|
|
@@ -1503,20 +1404,10 @@ int DLLEXPORT EN_setflowunits(EN_Project p, int units)
|
|
|
1503
1404
|
}
|
|
1504
1405
|
|
|
1505
1406
|
// Revise pressure units depending on flow units
|
|
1506
|
-
if (
|
|
1507
|
-
|
|
1508
|
-
if (p->parser.Unitsflag == US) p->parser.Pressflag = PSI;
|
|
1509
|
-
else p->parser.Pressflag = METERS;
|
|
1510
|
-
}
|
|
1407
|
+
if (p->parser.Unitsflag != SI) p->parser.Pressflag = PSI;
|
|
1408
|
+
else if (p->parser.Pressflag == PSI) p->parser.Pressflag = METERS;
|
|
1511
1409
|
initunits(p);
|
|
1512
1410
|
|
|
1513
|
-
// Update pressure units in rules
|
|
1514
|
-
dcf = Ucf[DEMAND] / dfactor;
|
|
1515
|
-
pcf = Ucf[PRESSURE] / pfactor;
|
|
1516
|
-
hcf = Ucf[HEAD] / hfactor;
|
|
1517
|
-
qcf = Ucf[FLOW] / qfactor;
|
|
1518
|
-
updateruleunits(p, dcf, pcf, hcf, qcf);
|
|
1519
|
-
|
|
1520
1411
|
//update curves
|
|
1521
1412
|
for (i = 1; i <= net->Ncurves; i++)
|
|
1522
1413
|
{
|
|
@@ -1700,65 +1591,12 @@ int DLLEXPORT EN_settimeparam(EN_Project p, int param, long value)
|
|
|
1700
1591
|
time->Qtime = value;
|
|
1701
1592
|
break;
|
|
1702
1593
|
|
|
1703
|
-
case EN_STARTTIME:
|
|
1704
|
-
if (value > SECperDAY) return 213;
|
|
1705
|
-
time->Tstart = value;
|
|
1706
|
-
break;
|
|
1707
|
-
|
|
1708
1594
|
default:
|
|
1709
1595
|
return 251;
|
|
1710
1596
|
}
|
|
1711
1597
|
return 0;
|
|
1712
1598
|
}
|
|
1713
1599
|
|
|
1714
|
-
|
|
1715
|
-
/// get the time to next event, and give a reason for the time step truncation
|
|
1716
|
-
int DLLEXPORT EN_timetonextevent(EN_Project p, int *eventType,
|
|
1717
|
-
long *duration, int *elementIndex)
|
|
1718
|
-
/*----------------------------------------------------------------
|
|
1719
|
-
** Input: none
|
|
1720
|
-
** Output: eventType = event causing a new time step
|
|
1721
|
-
** to occur (see EN_TimestepEvent)
|
|
1722
|
-
** duration = seconds until next time step occurs
|
|
1723
|
-
** elementIndex = index of tank node or simple control
|
|
1724
|
-
** that triggers a new time step
|
|
1725
|
-
** Returns: error code
|
|
1726
|
-
** Purpose: Get information about when the next hydraulic time step occurs
|
|
1727
|
-
**----------------------------------------------------------------
|
|
1728
|
-
*/
|
|
1729
|
-
{
|
|
1730
|
-
Times *time = &p->times;
|
|
1731
|
-
long hydStep, tankStep, controlStep;
|
|
1732
|
-
int iTank, iControl;
|
|
1733
|
-
|
|
1734
|
-
hydStep = time->Hstep;
|
|
1735
|
-
tankStep = hydStep;
|
|
1736
|
-
controlStep = hydStep;
|
|
1737
|
-
|
|
1738
|
-
iTank = tanktimestep(p, &tankStep);
|
|
1739
|
-
iControl = controltimestep(p, &controlStep);
|
|
1740
|
-
|
|
1741
|
-
// return the lesser of the three step lengths
|
|
1742
|
-
if (controlStep < tankStep) {
|
|
1743
|
-
*eventType = (int)EN_STEP_CONTROLEVENT;
|
|
1744
|
-
*duration = controlStep;
|
|
1745
|
-
*elementIndex = iControl;
|
|
1746
|
-
}
|
|
1747
|
-
else if (tankStep < hydStep) {
|
|
1748
|
-
*eventType = (int)EN_STEP_TANKEVENT;
|
|
1749
|
-
*duration = tankStep;
|
|
1750
|
-
*elementIndex = iTank;
|
|
1751
|
-
}
|
|
1752
|
-
else {
|
|
1753
|
-
*eventType = (int)EN_STEP_HYD;
|
|
1754
|
-
*duration = hydStep;
|
|
1755
|
-
*elementIndex = 0;
|
|
1756
|
-
}
|
|
1757
|
-
|
|
1758
|
-
return 0;
|
|
1759
|
-
}
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
1600
|
int DLLEXPORT EN_getqualinfo(EN_Project p, int *qualType, char *chemName,
|
|
1763
1601
|
char *chemUnits, int *traceNode)
|
|
1764
1602
|
/*----------------------------------------------------------------
|
|
@@ -1814,8 +1652,8 @@ int DLLEXPORT EN_getqualtype(EN_Project p, int *qualType, int *traceNode)
|
|
|
1814
1652
|
return 0;
|
|
1815
1653
|
}
|
|
1816
1654
|
|
|
1817
|
-
int DLLEXPORT EN_setqualtype(EN_Project p, int qualType,
|
|
1818
|
-
|
|
1655
|
+
int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, char *chemName,
|
|
1656
|
+
char *chemUnits, char *traceNode)
|
|
1819
1657
|
/*----------------------------------------------------------------
|
|
1820
1658
|
** Input: qualType = type of quality analysis to run (see EN_QualityType)
|
|
1821
1659
|
** chemname = name of chemical constituent
|
|
@@ -1832,7 +1670,7 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, const char *chemName,
|
|
|
1832
1670
|
Quality *qual = &p->quality;
|
|
1833
1671
|
|
|
1834
1672
|
double *Ucf = p->Ucf;
|
|
1835
|
-
int i, oldQualFlag, traceNodeIndex
|
|
1673
|
+
int i, oldQualFlag, traceNodeIndex;
|
|
1836
1674
|
double ccf = 1.0;
|
|
1837
1675
|
|
|
1838
1676
|
if (!p->Openflag) return 102;
|
|
@@ -1844,7 +1682,6 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, const char *chemName,
|
|
|
1844
1682
|
if (traceNodeIndex == 0) return 212;
|
|
1845
1683
|
}
|
|
1846
1684
|
|
|
1847
|
-
qual->TraceNode = traceNodeIndex;
|
|
1848
1685
|
oldQualFlag = qual->Qualflag;
|
|
1849
1686
|
qual->Qualflag = qualType;
|
|
1850
1687
|
qual->Ctol *= Ucf[QUALITY];
|
|
@@ -1859,6 +1696,8 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, const char *chemName,
|
|
|
1859
1696
|
}
|
|
1860
1697
|
if (qual->Qualflag == TRACE) // Source trace analysis
|
|
1861
1698
|
{
|
|
1699
|
+
qual->TraceNode = findnode(net, traceNode);
|
|
1700
|
+
if (qual->TraceNode == 0) return 212;
|
|
1862
1701
|
strncpy(qual->ChemName, w_TRACE, MAXID);
|
|
1863
1702
|
strncpy(qual->ChemUnits, u_PERCENT, MAXID);
|
|
1864
1703
|
strcpy(rpt->Field[QUALITY].Units, u_PERCENT);
|
|
@@ -1893,7 +1732,7 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, const char *chemName,
|
|
|
1893
1732
|
|
|
1894
1733
|
********************************************************************/
|
|
1895
1734
|
|
|
1896
|
-
int DLLEXPORT EN_addnode(EN_Project p,
|
|
1735
|
+
int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType, int *index)
|
|
1897
1736
|
/*----------------------------------------------------------------
|
|
1898
1737
|
** Input: id = node ID name
|
|
1899
1738
|
** nodeType = type of node (see EN_NodeType)
|
|
@@ -1922,21 +1761,17 @@ int DLLEXPORT EN_addnode(EN_Project p, const char *id, int nodeType, int *index)
|
|
|
1922
1761
|
|
|
1923
1762
|
// Check if a node with same id already exists
|
|
1924
1763
|
if (EN_getnodeindex(p, id, &i) == 0) return 215;
|
|
1925
|
-
|
|
1764
|
+
|
|
1926
1765
|
// Check for valid node type
|
|
1927
|
-
if (nodeType < EN_JUNCTION || nodeType > EN_TANK) return 251;
|
|
1766
|
+
if (nodeType < EN_JUNCTION || nodeType > EN_TANK) return 251;
|
|
1928
1767
|
|
|
1929
|
-
// Grow node-related arrays to
|
|
1768
|
+
// Grow node-related arrays to accomodate the new node
|
|
1930
1769
|
size = (net->Nnodes + 2) * sizeof(Snode);
|
|
1931
1770
|
net->Node = (Snode *)realloc(net->Node, size);
|
|
1932
1771
|
size = (net->Nnodes + 2) * sizeof(double);
|
|
1933
1772
|
hyd->NodeDemand = (double *)realloc(hyd->NodeDemand, size);
|
|
1934
1773
|
qual->NodeQual = (double *)realloc(qual->NodeQual, size);
|
|
1935
1774
|
hyd->NodeHead = (double *)realloc(hyd->NodeHead, size);
|
|
1936
|
-
hyd->FullDemand = (double *)realloc(hyd->FullDemand, size);
|
|
1937
|
-
hyd->EmitterFlow = (double *)realloc(hyd->EmitterFlow, size);
|
|
1938
|
-
hyd->LeakageFlow = (double *)realloc(hyd->LeakageFlow, size);
|
|
1939
|
-
hyd->DemandFlow = (double *)realloc(hyd->DemandFlow, size);
|
|
1940
1775
|
|
|
1941
1776
|
// Actions taken when a new Junction is added
|
|
1942
1777
|
if (nodeType == EN_JUNCTION)
|
|
@@ -1947,7 +1782,7 @@ int DLLEXPORT EN_addnode(EN_Project p, const char *id, int nodeType, int *index)
|
|
|
1947
1782
|
hashtable_update(net->NodeHashTable, net->Node[i].ID, i + 1);
|
|
1948
1783
|
net->Node[i + 1] = net->Node[i];
|
|
1949
1784
|
}
|
|
1950
|
-
|
|
1785
|
+
|
|
1951
1786
|
// set index of new Junction node
|
|
1952
1787
|
net->Njuncs++;
|
|
1953
1788
|
nIdx = net->Njuncs;
|
|
@@ -1973,7 +1808,7 @@ int DLLEXPORT EN_addnode(EN_Project p, const char *id, int nodeType, int *index)
|
|
|
1973
1808
|
if (control->Node > net->Njuncs - 1) control->Node += 1;
|
|
1974
1809
|
}
|
|
1975
1810
|
// adjust indices of tanks/reservoirs in Rule premises (see RULES.C)
|
|
1976
|
-
adjusttankrules(p
|
|
1811
|
+
adjusttankrules(p);
|
|
1977
1812
|
}
|
|
1978
1813
|
|
|
1979
1814
|
// Actions taken when a new Tank/Reservoir is added
|
|
@@ -2005,7 +1840,7 @@ int DLLEXPORT EN_addnode(EN_Project p, const char *id, int nodeType, int *index)
|
|
|
2005
1840
|
tank->Pat = 0;
|
|
2006
1841
|
tank->Vcurve = 0;
|
|
2007
1842
|
tank->MixModel = 0;
|
|
2008
|
-
tank->
|
|
1843
|
+
tank->V1max = 10000;
|
|
2009
1844
|
tank->CanOverflow = FALSE;
|
|
2010
1845
|
}
|
|
2011
1846
|
net->Nnodes++;
|
|
@@ -2023,7 +1858,6 @@ int DLLEXPORT EN_addnode(EN_Project p, const char *id, int nodeType, int *index)
|
|
|
2023
1858
|
node->X = MISSING;
|
|
2024
1859
|
node->Y = MISSING;
|
|
2025
1860
|
node->Comment = NULL;
|
|
2026
|
-
node->Tag = NULL;
|
|
2027
1861
|
|
|
2028
1862
|
// Insert new node into hash table
|
|
2029
1863
|
hashtable_insert(net->NodeHashTable, node->ID, nIdx);
|
|
@@ -2083,7 +1917,6 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode)
|
|
|
2083
1917
|
freedemands(node);
|
|
2084
1918
|
free(node->S);
|
|
2085
1919
|
free(node->Comment);
|
|
2086
|
-
free(node->Tag);
|
|
2087
1920
|
|
|
2088
1921
|
// Shift position of higher entries in Node & Coord arrays down one
|
|
2089
1922
|
for (i = index; i <= net->Nnodes - 1; i++)
|
|
@@ -2092,7 +1925,6 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode)
|
|
|
2092
1925
|
// ... update node's entry in the hash table
|
|
2093
1926
|
hashtable_update(net->NodeHashTable, net->Node[i].ID, i);
|
|
2094
1927
|
}
|
|
2095
|
-
if (index < p->quality.TraceNode) (p->quality.TraceNode)--;
|
|
2096
1928
|
|
|
2097
1929
|
// If deleted node is a tank, remove it from the Tank array
|
|
2098
1930
|
if (nodeType != EN_JUNCTION)
|
|
@@ -2147,7 +1979,7 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode)
|
|
|
2147
1979
|
return 0;
|
|
2148
1980
|
}
|
|
2149
1981
|
|
|
2150
|
-
int DLLEXPORT EN_getnodeindex(EN_Project p,
|
|
1982
|
+
int DLLEXPORT EN_getnodeindex(EN_Project p, char *id, int *index)
|
|
2151
1983
|
/*----------------------------------------------------------------
|
|
2152
1984
|
** Input: id = node ID name
|
|
2153
1985
|
** Output: index = node index
|
|
@@ -2179,7 +2011,7 @@ int DLLEXPORT EN_getnodeid(EN_Project p, int index, char *id)
|
|
|
2179
2011
|
return 0;
|
|
2180
2012
|
}
|
|
2181
2013
|
|
|
2182
|
-
int DLLEXPORT EN_setnodeid(EN_Project p, int index,
|
|
2014
|
+
int DLLEXPORT EN_setnodeid(EN_Project p, int index, char *newid)
|
|
2183
2015
|
/*----------------------------------------------------------------
|
|
2184
2016
|
** Input: index = node index
|
|
2185
2017
|
** newid = new node ID name
|
|
@@ -2242,10 +2074,8 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val
|
|
|
2242
2074
|
Network *net = &p->network;
|
|
2243
2075
|
Hydraul *hyd = &p->hydraul;
|
|
2244
2076
|
Quality *qual = &p->quality;
|
|
2245
|
-
Parser *parser = &p->parser;
|
|
2246
2077
|
|
|
2247
2078
|
double v = 0.0;
|
|
2248
|
-
double ecfTmp; // Unit conversion factor for emitter pressure
|
|
2249
2079
|
Psource source;
|
|
2250
2080
|
|
|
2251
2081
|
Snode *Node = net->Node;
|
|
@@ -2290,8 +2120,7 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val
|
|
|
2290
2120
|
v = 0.0;
|
|
2291
2121
|
if (Node[index].Ke > 0.0)
|
|
2292
2122
|
{
|
|
2293
|
-
|
|
2294
|
-
v = Ucf[FLOW] / pow((ecfTmp * Node[index].Ke), (1.0 / hyd->Qexp));
|
|
2123
|
+
v = Ucf[FLOW] / pow((Ucf[PRESSURE] * Node[index].Ke), (1.0 / hyd->Qexp));
|
|
2295
2124
|
}
|
|
2296
2125
|
break;
|
|
2297
2126
|
|
|
@@ -2328,12 +2157,10 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val
|
|
|
2328
2157
|
|
|
2329
2158
|
case EN_MIXZONEVOL:
|
|
2330
2159
|
v = 0.0;
|
|
2331
|
-
if (index > nJuncs)
|
|
2332
|
-
v = Tank[index - nJuncs].V1frac * Tank[index - nJuncs].Vmax *
|
|
2333
|
-
Ucf[VOLUME];
|
|
2160
|
+
if (index > nJuncs) v = Tank[index - nJuncs].V1max * Ucf[VOLUME];
|
|
2334
2161
|
break;
|
|
2335
2162
|
|
|
2336
|
-
case EN_DEMAND:
|
|
2163
|
+
case EN_DEMAND:
|
|
2337
2164
|
v = hyd->NodeDemand[index] * Ucf[FLOW];
|
|
2338
2165
|
break;
|
|
2339
2166
|
|
|
@@ -2390,9 +2217,9 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val
|
|
|
2390
2217
|
|
|
2391
2218
|
case EN_MIXFRACTION:
|
|
2392
2219
|
v = 1.0;
|
|
2393
|
-
if (index > nJuncs)
|
|
2220
|
+
if (index > nJuncs && Tank[index - nJuncs].Vmax > 0.0)
|
|
2394
2221
|
{
|
|
2395
|
-
v = Tank[index - nJuncs].
|
|
2222
|
+
v = Tank[index - nJuncs].V1max / Tank[index - nJuncs].Vmax;
|
|
2396
2223
|
}
|
|
2397
2224
|
break;
|
|
2398
2225
|
|
|
@@ -2410,34 +2237,14 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val
|
|
|
2410
2237
|
if (Node[index].Type != TANK) return 0;
|
|
2411
2238
|
v = Tank[index - nJuncs].CanOverflow;
|
|
2412
2239
|
break;
|
|
2413
|
-
|
|
2240
|
+
|
|
2414
2241
|
case EN_DEMANDDEFICIT:
|
|
2415
2242
|
if (index > nJuncs) return 0;
|
|
2416
|
-
//
|
|
2417
|
-
// while
|
|
2418
|
-
if (hyd->
|
|
2419
|
-
v = (hyd->
|
|
2420
|
-
|
|
2421
|
-
break;
|
|
2422
|
-
|
|
2423
|
-
case EN_NODE_INCONTROL:
|
|
2424
|
-
v = (double)incontrols(p, NODE, index);
|
|
2425
|
-
break;
|
|
2426
|
-
|
|
2427
|
-
case EN_EMITTERFLOW:
|
|
2428
|
-
v = hyd->EmitterFlow[index] * Ucf[FLOW];
|
|
2429
|
-
break;
|
|
2430
|
-
|
|
2431
|
-
case EN_LEAKAGEFLOW:
|
|
2432
|
-
v = hyd->LeakageFlow[index] * Ucf[FLOW];
|
|
2433
|
-
break;
|
|
2434
|
-
|
|
2435
|
-
case EN_DEMANDFLOW: // Consumer demand delivered
|
|
2436
|
-
v = hyd->DemandFlow[index] * Ucf[FLOW];
|
|
2437
|
-
break;
|
|
2438
|
-
|
|
2439
|
-
case EN_FULLDEMAND: // Consumer demand requested
|
|
2440
|
-
v = hyd->FullDemand[index] * Ucf[FLOW];
|
|
2243
|
+
// After an analysis, DemandFlow contains node's required demand
|
|
2244
|
+
// while NodeDemand contains delivered demand + emitter flow
|
|
2245
|
+
if (hyd->DemandFlow[index] < 0.0) return 0;
|
|
2246
|
+
v = (hyd->DemandFlow[index] -
|
|
2247
|
+
(hyd->NodeDemand[index] - hyd->EmitterFlow[index])) * Ucf[FLOW];
|
|
2441
2248
|
break;
|
|
2442
2249
|
|
|
2443
2250
|
default:
|
|
@@ -2447,25 +2254,6 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val
|
|
|
2447
2254
|
return 0;
|
|
2448
2255
|
}
|
|
2449
2256
|
|
|
2450
|
-
int DLLEXPORT EN_getnodevalues(EN_Project p, int property, double *values)
|
|
2451
|
-
/*----------------------------------------------------------------
|
|
2452
|
-
** Input: property = node property code (see EN_NodeProperty)
|
|
2453
|
-
** Output: values = array of node property values
|
|
2454
|
-
** Returns: error code
|
|
2455
|
-
** Purpose: retrieves an array of node property values
|
|
2456
|
-
**----------------------------------------------------------------
|
|
2457
|
-
*/
|
|
2458
|
-
{
|
|
2459
|
-
int errcode = 0, i = 0;
|
|
2460
|
-
|
|
2461
|
-
for (i = 1; i <= p->network.Nnodes; i++)
|
|
2462
|
-
{
|
|
2463
|
-
errcode = EN_getnodevalue(p, i, property, &values[i - 1]);
|
|
2464
|
-
if (errcode != 0) { return errcode; }
|
|
2465
|
-
}
|
|
2466
|
-
return 0;
|
|
2467
|
-
}
|
|
2468
|
-
|
|
2469
2257
|
int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double value)
|
|
2470
2258
|
/*----------------------------------------------------------------
|
|
2471
2259
|
** Input: index = node index
|
|
@@ -2480,7 +2268,6 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2480
2268
|
Network *net = &p->network;
|
|
2481
2269
|
Hydraul *hyd = &p->hydraul;
|
|
2482
2270
|
Quality *qual = &p->quality;
|
|
2483
|
-
Parser *parser = &p->parser;
|
|
2484
2271
|
|
|
2485
2272
|
Snode *Node = net->Node;
|
|
2486
2273
|
Stank *Tank = net->Tank;
|
|
@@ -2494,7 +2281,8 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2494
2281
|
|
|
2495
2282
|
int i, j, n;
|
|
2496
2283
|
Psource source;
|
|
2497
|
-
double hTmp
|
|
2284
|
+
double hTmp;
|
|
2285
|
+
double vTmp;
|
|
2498
2286
|
|
|
2499
2287
|
if (!p->Openflag) return 102;
|
|
2500
2288
|
if (index <= 0 || index > nNodes) return 203;
|
|
@@ -2536,13 +2324,8 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2536
2324
|
case EN_EMITTER:
|
|
2537
2325
|
if (index > nJuncs) return 0;
|
|
2538
2326
|
if (value < 0.0) return 209;
|
|
2539
|
-
if (value > 0.0)
|
|
2540
|
-
{
|
|
2541
|
-
ecfTmp = (parser->Unitsflag == US) ? (PSIperFT * hyd->SpGrav) : MperFT;
|
|
2542
|
-
value = pow((Ucf[FLOW] / value), hyd->Qexp) / ecfTmp;
|
|
2543
|
-
}
|
|
2327
|
+
if (value > 0.0) value = pow((Ucf[FLOW] / value), hyd->Qexp) / Ucf[PRESSURE];
|
|
2544
2328
|
Node[index].Ke = value;
|
|
2545
|
-
if (hyd->EmitterFlow[index] == 0.0) hyd->EmitterFlow[index] = 1.0;
|
|
2546
2329
|
break;
|
|
2547
2330
|
|
|
2548
2331
|
case EN_INITQUAL:
|
|
@@ -2581,7 +2364,7 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2581
2364
|
break;
|
|
2582
2365
|
|
|
2583
2366
|
case EN_TANKLEVEL:
|
|
2584
|
-
if (index <= nJuncs) return
|
|
2367
|
+
if (index <= nJuncs) return 0;
|
|
2585
2368
|
j = index - nJuncs;
|
|
2586
2369
|
if (Tank[j].A == 0.0) /* Tank is a reservoir */
|
|
2587
2370
|
{
|
|
@@ -2605,9 +2388,9 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2605
2388
|
|
|
2606
2389
|
case EN_TANKDIAM:
|
|
2607
2390
|
if (value <= 0.0) return 209; // invalid diameter
|
|
2608
|
-
if (index <= nJuncs) return
|
|
2391
|
+
if (index <= nJuncs) return 0; // node is not a tank
|
|
2609
2392
|
j = index - nJuncs; // tank index
|
|
2610
|
-
if (Tank[j].A == 0.0) return
|
|
2393
|
+
if (Tank[j].A == 0.0) return 0; // tank is a reservoir
|
|
2611
2394
|
value /= Ucf[ELEV]; // diameter in feet
|
|
2612
2395
|
Tank[j].A = PI * SQR(value) / 4.0; // new tank area
|
|
2613
2396
|
if (Tank[j].Vcurve > 0) // tank has a volume curve
|
|
@@ -2616,7 +2399,7 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2616
2399
|
|
|
2617
2400
|
// Since the volume curve no longer applies we assume that the tank's
|
|
2618
2401
|
// shape below Hmin is cylindrical and Vmin equals area times Hmin
|
|
2619
|
-
Tank[j].Vmin = Tank[j].A *
|
|
2402
|
+
Tank[j].Vmin = Tank[j].A * Tank[j].Hmin;
|
|
2620
2403
|
}
|
|
2621
2404
|
// Since tank's area has changed its volumes must be updated
|
|
2622
2405
|
// NOTE: For a non-volume curve tank we can't change the Vmin
|
|
@@ -2624,14 +2407,16 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2624
2407
|
// shape below Hmin. Vmin can always be changed by setting
|
|
2625
2408
|
// EN_MINVOLUME in a subsequent function call.
|
|
2626
2409
|
Tank[j].V0 = tankvolume(p, j, Tank[j].H0); // new init. volume
|
|
2410
|
+
vTmp = Tank[j].Vmax; // old max. volume
|
|
2627
2411
|
Tank[j].Vmax = tankvolume(p, j, Tank[j].Hmax); // new max. volume
|
|
2412
|
+
Tank[j].V1max *= Tank[j].Vmax / vTmp; // new mix zone volume
|
|
2628
2413
|
break;
|
|
2629
2414
|
|
|
2630
2415
|
case EN_MINVOLUME:
|
|
2631
2416
|
if (value < 0.0) return 209; // invalid volume
|
|
2632
|
-
if (index <= nJuncs) return
|
|
2417
|
+
if (index <= nJuncs) return 0; // node is not a tank
|
|
2633
2418
|
j = index - nJuncs; // tank index
|
|
2634
|
-
if (Tank[j].A == 0.0) return
|
|
2419
|
+
if (Tank[j].A == 0.0) return 0; // tank is a reservoir
|
|
2635
2420
|
i = Tank[j].Vcurve; // volume curve index
|
|
2636
2421
|
if (i > 0) // tank has a volume curve
|
|
2637
2422
|
{
|
|
@@ -2649,12 +2434,14 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2649
2434
|
// If the volume supplied by the function is 0 then the tank shape
|
|
2650
2435
|
// below Hmin is assumed to be cylindrical and a new Vmin value is
|
|
2651
2436
|
// computed. Otherwise Vmin is set to the supplied value.
|
|
2652
|
-
if (value == 0.0) Tank[j].Vmin = Tank[j].A *
|
|
2437
|
+
if (value == 0.0) Tank[j].Vmin = Tank[j].A * Tank[j].Hmin;
|
|
2653
2438
|
else Tank[j].Vmin = value / Ucf[VOLUME];
|
|
2654
2439
|
|
|
2655
2440
|
// Since Vmin changes the other volumes need updating
|
|
2656
2441
|
Tank[j].V0 = tankvolume(p, j, Tank[j].H0); // new init. volume
|
|
2442
|
+
vTmp = Tank[j].Vmax; // old max. volume
|
|
2657
2443
|
Tank[j].Vmax = tankvolume(p, j, Tank[j].Hmax); // new max. volume
|
|
2444
|
+
Tank[j].V1max *= Tank[j].Vmax / vTmp; // new mix zone volume
|
|
2658
2445
|
}
|
|
2659
2446
|
break;
|
|
2660
2447
|
|
|
@@ -2664,9 +2451,9 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2664
2451
|
i = ROUND(value); // curve index
|
|
2665
2452
|
if (i <= 0 ||
|
|
2666
2453
|
i > net->Ncurves) return 205; // invalid curve index
|
|
2667
|
-
if (index <= nJuncs) return
|
|
2454
|
+
if (index <= nJuncs) return 0; // node not a tank
|
|
2668
2455
|
j = index - nJuncs; // tank index
|
|
2669
|
-
if (Tank[j].A == 0.0) return
|
|
2456
|
+
if (Tank[j].A == 0.0) return 0; // tank is a reservoir
|
|
2670
2457
|
curve = &net->Curve[i]; // curve object
|
|
2671
2458
|
|
|
2672
2459
|
// Check that tank's min/max levels lie within curve
|
|
@@ -2679,16 +2466,18 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2679
2466
|
Tank[j].Vcurve = i; // assign curve to tank
|
|
2680
2467
|
Tank[j].Vmin = tankvolume(p, j, Tank[j].Hmin); // new min. volume
|
|
2681
2468
|
Tank[j].V0 = tankvolume(p, j, Tank[j].H0); // new init. volume
|
|
2469
|
+
vTmp = Tank[j].Vmax; // old max. volume
|
|
2682
2470
|
Tank[j].Vmax = tankvolume(p, j, Tank[j].Hmax); // new max. volume
|
|
2683
|
-
Tank[j].
|
|
2471
|
+
Tank[j].V1max *= Tank[j].Vmax / vTmp; // new mix zone volume
|
|
2472
|
+
Tank[j].A = (curve->Y[n] - curve->Y[0]) / // nominal area
|
|
2684
2473
|
(curve->X[n] - curve->X[0]);
|
|
2685
2474
|
break;
|
|
2686
2475
|
|
|
2687
2476
|
case EN_MINLEVEL:
|
|
2688
2477
|
if (value < 0.0) return 209; // invalid water level
|
|
2689
|
-
if (index <= nJuncs) return
|
|
2478
|
+
if (index <= nJuncs) return 0; // node not a tank
|
|
2690
2479
|
j = index - nJuncs; // tank index
|
|
2691
|
-
if (Tank[j].A == 0.0) return
|
|
2480
|
+
if (Tank[j].A == 0.0) return 0; // tank is a reservoir
|
|
2692
2481
|
hTmp = value / Ucf[ELEV] + Node[index].El; // convert level to head
|
|
2693
2482
|
if (hTmp >= Tank[j].Hmax ||
|
|
2694
2483
|
hTmp > Tank[j].H0) return 225; // invalid water levels
|
|
@@ -2707,9 +2496,9 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2707
2496
|
|
|
2708
2497
|
case EN_MAXLEVEL:
|
|
2709
2498
|
if (value <= 0.0) return 209; // invalid water level
|
|
2710
|
-
if (index <= nJuncs) return
|
|
2499
|
+
if (index <= nJuncs) return 0; // node not a tank
|
|
2711
2500
|
j = index - nJuncs; // tank index
|
|
2712
|
-
if (Tank[j].A == 0.0) return
|
|
2501
|
+
if (Tank[j].A == 0.0) return 0; // tank is a reservoir
|
|
2713
2502
|
hTmp = value / Ucf[ELEV] + Node[index].El; // convert level to head
|
|
2714
2503
|
if (hTmp < Tank[j].Hmin ||
|
|
2715
2504
|
hTmp < Tank[j].H0) return 225; // invalid water levels
|
|
@@ -2721,12 +2510,14 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2721
2510
|
if (value > curve->X[n]) return 225; // new level is off curve
|
|
2722
2511
|
}
|
|
2723
2512
|
Tank[j].Hmax = hTmp; // new max. head
|
|
2513
|
+
vTmp = Tank[j].Vmax; // old max. volume
|
|
2724
2514
|
Tank[j].Vmax = tankvolume(p, j, hTmp); // new max. volume
|
|
2515
|
+
Tank[j].V1max *= Tank[j].Vmax / vTmp; // new mix zone volume
|
|
2725
2516
|
break;
|
|
2726
2517
|
|
|
2727
2518
|
case EN_MIXMODEL:
|
|
2728
2519
|
j = ROUND(value);
|
|
2729
|
-
if (index <= nJuncs) return
|
|
2520
|
+
if (index <= nJuncs) return 0;
|
|
2730
2521
|
if (j < MIX1 || j > LIFO) return 251;
|
|
2731
2522
|
if (Tank[index - nJuncs].A > 0.0)
|
|
2732
2523
|
{
|
|
@@ -2735,17 +2526,17 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2735
2526
|
break;
|
|
2736
2527
|
|
|
2737
2528
|
case EN_MIXFRACTION:
|
|
2738
|
-
if (index <= nJuncs) return
|
|
2529
|
+
if (index <= nJuncs) return 0;
|
|
2739
2530
|
if (value < 0.0 || value > 1.0) return 209;
|
|
2740
2531
|
j = index - nJuncs;
|
|
2741
2532
|
if (Tank[j].A > 0.0)
|
|
2742
2533
|
{
|
|
2743
|
-
Tank[j].
|
|
2534
|
+
Tank[j].V1max = value * Tank[j].Vmax;
|
|
2744
2535
|
}
|
|
2745
2536
|
break;
|
|
2746
2537
|
|
|
2747
2538
|
case EN_TANK_KBULK:
|
|
2748
|
-
if (index <= nJuncs) return
|
|
2539
|
+
if (index <= nJuncs) return 0;
|
|
2749
2540
|
j = index - nJuncs;
|
|
2750
2541
|
if (Tank[j].A > 0.0)
|
|
2751
2542
|
{
|
|
@@ -2755,7 +2546,7 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2755
2546
|
break;
|
|
2756
2547
|
|
|
2757
2548
|
case EN_CANOVERFLOW:
|
|
2758
|
-
if (Node[index].Type != TANK) return
|
|
2549
|
+
if (Node[index].Type != TANK) return 0;
|
|
2759
2550
|
Tank[index - nJuncs].CanOverflow = (value != 0.0);
|
|
2760
2551
|
break;
|
|
2761
2552
|
|
|
@@ -2766,7 +2557,7 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2766
2557
|
}
|
|
2767
2558
|
|
|
2768
2559
|
int DLLEXPORT EN_setjuncdata(EN_Project p, int index, double elev,
|
|
2769
|
-
double dmnd,
|
|
2560
|
+
double dmnd, char *dmndpat)
|
|
2770
2561
|
/*----------------------------------------------------------------
|
|
2771
2562
|
** Input: index = junction node index
|
|
2772
2563
|
** elev = junction elevation
|
|
@@ -2811,7 +2602,7 @@ int DLLEXPORT EN_setjuncdata(EN_Project p, int index, double elev,
|
|
|
2811
2602
|
int DLLEXPORT EN_settankdata(EN_Project p, int index, double elev,
|
|
2812
2603
|
double initlvl, double minlvl,
|
|
2813
2604
|
double maxlvl, double diam,
|
|
2814
|
-
double minvol,
|
|
2605
|
+
double minvol, char *volcurve)
|
|
2815
2606
|
/*----------------------------------------------------------------
|
|
2816
2607
|
** Input: index = tank node index
|
|
2817
2608
|
** elev = tank bottom elevation
|
|
@@ -2830,16 +2621,16 @@ int DLLEXPORT EN_settankdata(EN_Project p, int index, double elev,
|
|
|
2830
2621
|
Network *net = &p->network;
|
|
2831
2622
|
|
|
2832
2623
|
int i, j, n, curveIndex = 0;
|
|
2624
|
+
double area, elevation = elev;
|
|
2833
2625
|
double *Ucf = p->Ucf;
|
|
2834
|
-
double area;
|
|
2835
2626
|
Stank *Tank = net->Tank;
|
|
2836
2627
|
Scurve *curve;
|
|
2837
2628
|
|
|
2838
2629
|
// Check that tank exists
|
|
2839
2630
|
if (!p->Openflag) return 102;
|
|
2840
|
-
if (index <= net->Njuncs || index > net->Nnodes) return
|
|
2631
|
+
if (index <= net->Njuncs || index > net->Nnodes) return 203;
|
|
2841
2632
|
j = index - net->Njuncs;
|
|
2842
|
-
if (Tank[j].A == 0) return
|
|
2633
|
+
if (Tank[j].A == 0) return 0; // Tank is a Reservoir
|
|
2843
2634
|
|
|
2844
2635
|
// Check for valid parameter values
|
|
2845
2636
|
if (initlvl < 0.0 || minlvl < 0.0 || maxlvl < 0.0) return 209;
|
|
@@ -2868,16 +2659,16 @@ int DLLEXPORT EN_settankdata(EN_Project p, int index, double elev,
|
|
|
2868
2659
|
else area = PI * diam * diam / 4.0;
|
|
2869
2660
|
|
|
2870
2661
|
// Assign parameters to tank object
|
|
2871
|
-
net->Node[Tank[j].Node].El =
|
|
2662
|
+
net->Node[Tank[j].Node].El = elevation;
|
|
2872
2663
|
Tank[j].A = area / Ucf[ELEV] / Ucf[ELEV];
|
|
2873
|
-
Tank[j].H0 =
|
|
2874
|
-
Tank[j].Hmin =
|
|
2875
|
-
Tank[j].Hmax =
|
|
2664
|
+
Tank[j].H0 = elevation + initlvl / Ucf[ELEV];
|
|
2665
|
+
Tank[j].Hmin = elevation + minlvl / Ucf[ELEV];
|
|
2666
|
+
Tank[j].Hmax = elevation + maxlvl / Ucf[ELEV];
|
|
2876
2667
|
Tank[j].Vcurve = curveIndex;
|
|
2877
2668
|
if (curveIndex == 0)
|
|
2878
2669
|
{
|
|
2879
2670
|
if (minvol > 0.0) Tank[j].Vmin = minvol / Ucf[VOLUME];
|
|
2880
|
-
else Tank[j].Vmin = Tank[j].A *
|
|
2671
|
+
else Tank[j].Vmin = Tank[j].A * Tank[j].Hmin;
|
|
2881
2672
|
}
|
|
2882
2673
|
else Tank[j].Vmin = tankvolume(p, j, Tank[j].Hmin);
|
|
2883
2674
|
Tank[j].V0 = tankvolume(p, j, Tank[j].H0);
|
|
@@ -2987,7 +2778,7 @@ int DLLEXPORT EN_setdemandmodel(EN_Project p, int model, double pmin,
|
|
|
2987
2778
|
}
|
|
2988
2779
|
|
|
2989
2780
|
int DLLEXPORT EN_adddemand(EN_Project p, int nodeIndex, double baseDemand,
|
|
2990
|
-
|
|
2781
|
+
char *demandPattern, char *demandName)
|
|
2991
2782
|
/*----------------------------------------------------------------
|
|
2992
2783
|
** Input: nodeIndex = node index
|
|
2993
2784
|
** baseDemand = baseline demand value
|
|
@@ -3074,7 +2865,7 @@ int DLLEXPORT EN_deletedemand(EN_Project p, int nodeIndex, int demandIndex)
|
|
|
3074
2865
|
return 0;
|
|
3075
2866
|
}
|
|
3076
2867
|
|
|
3077
|
-
int DLLEXPORT EN_getdemandindex(EN_Project p, int nodeIndex,
|
|
2868
|
+
int DLLEXPORT EN_getdemandindex(EN_Project p, int nodeIndex, char *demandName,
|
|
3078
2869
|
int *demandIndex)
|
|
3079
2870
|
/*----------------------------------------------------------------
|
|
3080
2871
|
** Input: nodeIndex = node index
|
|
@@ -3223,7 +3014,7 @@ int DLLEXPORT EN_getdemandname(EN_Project p, int nodeIndex, int demandIndex,
|
|
|
3223
3014
|
}
|
|
3224
3015
|
|
|
3225
3016
|
int DLLEXPORT EN_setdemandname(EN_Project p, int nodeIndex, int demandIndex,
|
|
3226
|
-
|
|
3017
|
+
char *demandName)
|
|
3227
3018
|
/*----------------------------------------------------------------
|
|
3228
3019
|
** Input: nodeIndex = node index
|
|
3229
3020
|
** demandIndex = demand category index
|
|
@@ -3313,8 +3104,8 @@ int DLLEXPORT EN_setdemandpattern(EN_Project p, int nodeIndex, int demandIndex,
|
|
|
3313
3104
|
|
|
3314
3105
|
********************************************************************/
|
|
3315
3106
|
|
|
3316
|
-
int DLLEXPORT EN_addlink(EN_Project p,
|
|
3317
|
-
|
|
3107
|
+
int DLLEXPORT EN_addlink(EN_Project p, char *id, int linkType,
|
|
3108
|
+
char *fromNode, char *toNode, int *index)
|
|
3318
3109
|
/*----------------------------------------------------------------
|
|
3319
3110
|
** Input: id = link ID name
|
|
3320
3111
|
** type = link type (see EN_LinkType)
|
|
@@ -3346,7 +3137,7 @@ int DLLEXPORT EN_addlink(EN_Project p, const char *id, int linkType,
|
|
|
3346
3137
|
if (EN_getlinkindex(p, id, &i) == 0) return 215;
|
|
3347
3138
|
|
|
3348
3139
|
// Check for valid link type
|
|
3349
|
-
if (linkType < CVPIPE || linkType >
|
|
3140
|
+
if (linkType < CVPIPE || linkType > GPV) return 251;
|
|
3350
3141
|
|
|
3351
3142
|
// Lookup the link's from and to nodes
|
|
3352
3143
|
n1 = hashtable_find(net->NodeHashTable, fromNode);
|
|
@@ -3360,7 +3151,7 @@ int DLLEXPORT EN_addlink(EN_Project p, const char *id, int linkType,
|
|
|
3360
3151
|
if (errcode) return errcode;
|
|
3361
3152
|
}
|
|
3362
3153
|
|
|
3363
|
-
// Grow link-related arrays to
|
|
3154
|
+
// Grow link-related arrays to accomodate the new link
|
|
3364
3155
|
net->Nlinks++;
|
|
3365
3156
|
p->parser.MaxLinks = net->Nlinks;
|
|
3366
3157
|
n = net->Nlinks;
|
|
@@ -3379,7 +3170,7 @@ int DLLEXPORT EN_addlink(EN_Project p, const char *id, int linkType,
|
|
|
3379
3170
|
if (linkType <= PIPE) net->Npipes++;
|
|
3380
3171
|
else if (linkType == PUMP)
|
|
3381
3172
|
{
|
|
3382
|
-
// Grow pump array to
|
|
3173
|
+
// Grow pump array to accomodate the new link
|
|
3383
3174
|
net->Npumps++;
|
|
3384
3175
|
size = (net->Npumps + 1) * sizeof(Spump);
|
|
3385
3176
|
net->Pump = (Spump *)realloc(net->Pump, size);
|
|
@@ -3401,18 +3192,17 @@ int DLLEXPORT EN_addlink(EN_Project p, const char *id, int linkType,
|
|
|
3401
3192
|
}
|
|
3402
3193
|
else
|
|
3403
3194
|
{
|
|
3404
|
-
// Grow valve array to
|
|
3195
|
+
// Grow valve array to accomodate the new link
|
|
3405
3196
|
net->Nvalves++;
|
|
3406
3197
|
size = (net->Nvalves + 1) * sizeof(Svalve);
|
|
3407
3198
|
net->Valve = (Svalve *)realloc(net->Valve, size);
|
|
3408
3199
|
net->Valve[net->Nvalves].Link = n;
|
|
3409
|
-
net->Valve[net->Nvalves].Curve = 0;
|
|
3410
3200
|
}
|
|
3411
3201
|
|
|
3412
3202
|
link->Type = linkType;
|
|
3413
3203
|
link->N1 = n1;
|
|
3414
3204
|
link->N2 = n2;
|
|
3415
|
-
link->
|
|
3205
|
+
link->Status = OPEN;
|
|
3416
3206
|
|
|
3417
3207
|
if (linkType == PUMP)
|
|
3418
3208
|
{
|
|
@@ -3441,19 +3231,15 @@ int DLLEXPORT EN_addlink(EN_Project p, const char *id, int linkType,
|
|
|
3441
3231
|
link->Kc = 0.0; // Valve setting.
|
|
3442
3232
|
link->Km = 0.0; // Loss coeff
|
|
3443
3233
|
link->Len = 0.0;
|
|
3444
|
-
link->
|
|
3234
|
+
link->Status = ACTIVE;
|
|
3445
3235
|
}
|
|
3446
3236
|
link->Kb = 0;
|
|
3447
3237
|
link->Kw = 0;
|
|
3448
|
-
link->LeakArea = 0;
|
|
3449
|
-
link->LeakExpan = 0;
|
|
3450
|
-
link->InitSetting = link->Kc;
|
|
3451
3238
|
link->R = 0;
|
|
3452
3239
|
link->Rc = 0;
|
|
3453
3240
|
link->Rpt = 0;
|
|
3454
3241
|
link->ResultIndex = 0;
|
|
3455
3242
|
link->Comment = NULL;
|
|
3456
|
-
link->Tag = NULL;
|
|
3457
3243
|
link->Vertices = NULL;
|
|
3458
3244
|
|
|
3459
3245
|
hashtable_insert(net->LinkHashTable, link->ID, n);
|
|
@@ -3506,7 +3292,6 @@ int DLLEXPORT EN_deletelink(EN_Project p, int index, int actionCode)
|
|
|
3506
3292
|
|
|
3507
3293
|
// Remove link's comment and vertices
|
|
3508
3294
|
free(link->Comment);
|
|
3509
|
-
free(link->Tag);
|
|
3510
3295
|
freelinkvertices(link);
|
|
3511
3296
|
|
|
3512
3297
|
// Shift position of higher entries in Link array down one
|
|
@@ -3527,12 +3312,6 @@ int DLLEXPORT EN_deletelink(EN_Project p, int index, int actionCode)
|
|
|
3527
3312
|
if (net->Valve[i].Link > index) net->Valve[i].Link -= 1;
|
|
3528
3313
|
}
|
|
3529
3314
|
|
|
3530
|
-
// Reduce the number of pipes count by one if it is a pipe.
|
|
3531
|
-
if (linkType == PIPE)
|
|
3532
|
-
{
|
|
3533
|
-
net->Npipes--;
|
|
3534
|
-
}
|
|
3535
|
-
|
|
3536
3315
|
// Delete any pump associated with the deleted link
|
|
3537
3316
|
if (linkType == PUMP)
|
|
3538
3317
|
{
|
|
@@ -3575,7 +3354,7 @@ int DLLEXPORT EN_deletelink(EN_Project p, int index, int actionCode)
|
|
|
3575
3354
|
return 0;
|
|
3576
3355
|
}
|
|
3577
3356
|
|
|
3578
|
-
int DLLEXPORT EN_getlinkindex(EN_Project p,
|
|
3357
|
+
int DLLEXPORT EN_getlinkindex(EN_Project p, char *id, int *index)
|
|
3579
3358
|
/*----------------------------------------------------------------
|
|
3580
3359
|
** Input: id = link ID name
|
|
3581
3360
|
** Output: index = link index
|
|
@@ -3607,7 +3386,7 @@ int DLLEXPORT EN_getlinkid(EN_Project p, int index, char *id)
|
|
|
3607
3386
|
return 0;
|
|
3608
3387
|
}
|
|
3609
3388
|
|
|
3610
|
-
int DLLEXPORT EN_setlinkid(EN_Project p, int index,
|
|
3389
|
+
int DLLEXPORT EN_setlinkid(EN_Project p, int index, char *newid)
|
|
3611
3390
|
/*----------------------------------------------------------------
|
|
3612
3391
|
** Input: index = link index
|
|
3613
3392
|
** id = link ID name
|
|
@@ -3677,7 +3456,7 @@ int DLLEXPORT EN_setlinktype(EN_Project p, int *index, int linkType, int actionC
|
|
|
3677
3456
|
if (p->hydraul.OpenHflag || p->quality.OpenQflag) return 262;
|
|
3678
3457
|
|
|
3679
3458
|
// Check for valid input parameters
|
|
3680
|
-
if (linkType < 0 || linkType >
|
|
3459
|
+
if (linkType < 0 || linkType > GPV || actionCode < EN_UNCONDITIONAL ||
|
|
3681
3460
|
actionCode > EN_CONDITIONAL)
|
|
3682
3461
|
{
|
|
3683
3462
|
return 251;
|
|
@@ -3701,7 +3480,7 @@ int DLLEXPORT EN_setlinktype(EN_Project p, int *index, int linkType, int actionC
|
|
|
3701
3480
|
if (oldType <= PIPE && linkType <= PIPE)
|
|
3702
3481
|
{
|
|
3703
3482
|
net->Link[i].Type = linkType;
|
|
3704
|
-
if (linkType == CVPIPE) net->Link[i].
|
|
3483
|
+
if (linkType == CVPIPE) net->Link[i].Status = OPEN;
|
|
3705
3484
|
return 0;
|
|
3706
3485
|
}
|
|
3707
3486
|
|
|
@@ -3804,6 +3583,8 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val
|
|
|
3804
3583
|
Slink *Link = net->Link;
|
|
3805
3584
|
Spump *Pump = net->Pump;
|
|
3806
3585
|
double *Ucf = p->Ucf;
|
|
3586
|
+
double *LinkFlow = hyd->LinkFlow;
|
|
3587
|
+
double *LinkSetting = hyd->LinkSetting;
|
|
3807
3588
|
|
|
3808
3589
|
// Check for valid arguments
|
|
3809
3590
|
*value = 0.0;
|
|
@@ -3841,19 +3622,18 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val
|
|
|
3841
3622
|
break;
|
|
3842
3623
|
|
|
3843
3624
|
case EN_INITSTATUS:
|
|
3844
|
-
if (Link[index].
|
|
3625
|
+
if (Link[index].Status <= CLOSED) v = 0.0;
|
|
3845
3626
|
else v = 1.0;
|
|
3846
|
-
if (Link[index].Type > PUMP && Link[index].InitStatus > OPEN) v = 2.0;
|
|
3847
3627
|
break;
|
|
3848
3628
|
|
|
3849
3629
|
case EN_INITSETTING:
|
|
3850
|
-
|
|
3630
|
+
if (Link[index].Type == PIPE || Link[index].Type == CVPIPE)
|
|
3631
|
+
{
|
|
3632
|
+
return EN_getlinkvalue(p, index, EN_ROUGHNESS, value);
|
|
3633
|
+
}
|
|
3634
|
+
v = Link[index].Kc;
|
|
3851
3635
|
switch (Link[index].Type)
|
|
3852
3636
|
{
|
|
3853
|
-
case CVPIPE:
|
|
3854
|
-
case PIPE:
|
|
3855
|
-
if (hyd->Formflag == DW) v = v * (1000.0 * Ucf[ELEV]);
|
|
3856
|
-
break;
|
|
3857
3637
|
case PRV:
|
|
3858
3638
|
case PSV:
|
|
3859
3639
|
case PBV:
|
|
@@ -3876,7 +3656,7 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val
|
|
|
3876
3656
|
|
|
3877
3657
|
case EN_FLOW:
|
|
3878
3658
|
if (hyd->LinkStatus[index] <= CLOSED) v = 0.0;
|
|
3879
|
-
else v =
|
|
3659
|
+
else v = LinkFlow[index] * Ucf[FLOW];
|
|
3880
3660
|
break;
|
|
3881
3661
|
|
|
3882
3662
|
case EN_VELOCITY:
|
|
@@ -3884,7 +3664,7 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val
|
|
|
3884
3664
|
else if (hyd->LinkStatus[index] <= CLOSED) v = 0.0;
|
|
3885
3665
|
else
|
|
3886
3666
|
{
|
|
3887
|
-
q = ABS(
|
|
3667
|
+
q = ABS(LinkFlow[index]);
|
|
3888
3668
|
a = PI * SQR(Link[index].Diam) / 4.0;
|
|
3889
3669
|
v = q / a * Ucf[VELOCITY];
|
|
3890
3670
|
}
|
|
@@ -3903,8 +3683,6 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val
|
|
|
3903
3683
|
case EN_STATUS:
|
|
3904
3684
|
if (hyd->LinkStatus[index] <= CLOSED) v = 0.0;
|
|
3905
3685
|
else v = 1.0;
|
|
3906
|
-
if (Link[index].Type > PUMP &&
|
|
3907
|
-
hyd->LinkStatus[index] > OPEN) v = 2.0;
|
|
3908
3686
|
break;
|
|
3909
3687
|
|
|
3910
3688
|
case EN_SETTING:
|
|
@@ -3912,8 +3690,8 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val
|
|
|
3912
3690
|
{
|
|
3913
3691
|
return EN_getlinkvalue(p, index, EN_ROUGHNESS, value);
|
|
3914
3692
|
}
|
|
3915
|
-
if (
|
|
3916
|
-
else v =
|
|
3693
|
+
if (LinkSetting[index] == MISSING) v = 0.0;
|
|
3694
|
+
else v = LinkSetting[index];
|
|
3917
3695
|
switch (Link[index].Type)
|
|
3918
3696
|
{
|
|
3919
3697
|
case PRV:
|
|
@@ -4000,40 +3778,6 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val
|
|
|
4000
3778
|
v = (double)Pump[findpump(&p->network, index)].Epat;
|
|
4001
3779
|
}
|
|
4002
3780
|
break;
|
|
4003
|
-
|
|
4004
|
-
case EN_PCV_CURVE:
|
|
4005
|
-
if (Link[index].Type == PCV)
|
|
4006
|
-
{
|
|
4007
|
-
v = net->Valve[findvalve(&p->network, index)].Curve;
|
|
4008
|
-
}
|
|
4009
|
-
break;
|
|
4010
|
-
|
|
4011
|
-
case EN_GPV_CURVE:
|
|
4012
|
-
if (Link[index].Type == GPV)
|
|
4013
|
-
{
|
|
4014
|
-
v = Link[index].Kc;
|
|
4015
|
-
}
|
|
4016
|
-
break;
|
|
4017
|
-
|
|
4018
|
-
case EN_LINK_INCONTROL:
|
|
4019
|
-
v = (double)incontrols(p, LINK, index);
|
|
4020
|
-
break;
|
|
4021
|
-
|
|
4022
|
-
case EN_LEAK_AREA:
|
|
4023
|
-
v = Link[index].LeakArea * Ucf[LENGTH];
|
|
4024
|
-
break;
|
|
4025
|
-
|
|
4026
|
-
case EN_LEAK_EXPAN:
|
|
4027
|
-
v = Link[index].LeakExpan * Ucf[LENGTH];
|
|
4028
|
-
break;
|
|
4029
|
-
|
|
4030
|
-
case EN_LINK_LEAKAGE:
|
|
4031
|
-
v = findlinkleakage(p, index) * Ucf[FLOW];
|
|
4032
|
-
break;
|
|
4033
|
-
|
|
4034
|
-
case EN_VALVE_TYPE:
|
|
4035
|
-
if (Link[index].Type > PUMP) v = Link[index].Type;
|
|
4036
|
-
break;
|
|
4037
3781
|
|
|
4038
3782
|
default:
|
|
4039
3783
|
return 251;
|
|
@@ -4042,24 +3786,6 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val
|
|
|
4042
3786
|
return 0;
|
|
4043
3787
|
}
|
|
4044
3788
|
|
|
4045
|
-
int DLLEXPORT EN_getlinkvalues(EN_Project p, int property, double *values)
|
|
4046
|
-
/*----------------------------------------------------------------
|
|
4047
|
-
** Input: property = link property code (see EN_LinkProperty)
|
|
4048
|
-
** Output: values = array of link property values
|
|
4049
|
-
** Returns: error code
|
|
4050
|
-
** Purpose: retrieves property values for all links
|
|
4051
|
-
**----------------------------------------------------------------
|
|
4052
|
-
*/
|
|
4053
|
-
{
|
|
4054
|
-
int errcode = 0, i = 0;
|
|
4055
|
-
for(i = 1; i <= p->network.Nlinks; i++)
|
|
4056
|
-
{
|
|
4057
|
-
errcode = EN_getlinkvalue(p, i, property, &values[i-1]);
|
|
4058
|
-
if(errcode != 0) { return errcode; }
|
|
4059
|
-
}
|
|
4060
|
-
return 0;
|
|
4061
|
-
}
|
|
4062
|
-
|
|
4063
3789
|
int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double value)
|
|
4064
3790
|
/*----------------------------------------------------------------
|
|
4065
3791
|
** Input: index = link index
|
|
@@ -4077,9 +3803,10 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu
|
|
|
4077
3803
|
|
|
4078
3804
|
Slink *Link = net->Link;
|
|
4079
3805
|
double *Ucf = p->Ucf;
|
|
3806
|
+
double *LinkSetting = hyd->LinkSetting;
|
|
4080
3807
|
char s;
|
|
4081
3808
|
double r;
|
|
4082
|
-
int pumpIndex, patIndex, curveIndex
|
|
3809
|
+
int pumpIndex, patIndex, curveIndex;
|
|
4083
3810
|
|
|
4084
3811
|
if (!p->Openflag) return 102;
|
|
4085
3812
|
if (index <= 0 || index > net->Nlinks) return 204;
|
|
@@ -4112,15 +3839,14 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu
|
|
|
4112
3839
|
if (value <= 0.0) return 211;
|
|
4113
3840
|
Link[index].Kc = value;
|
|
4114
3841
|
if (hyd->Formflag == DW) Link[index].Kc /= (1000.0 * Ucf[ELEV]);
|
|
4115
|
-
|
|
4116
|
-
else Link[index].InitSetting = Link[index].Kc;
|
|
3842
|
+
resistcoeff(p, index);
|
|
4117
3843
|
}
|
|
4118
3844
|
break;
|
|
4119
3845
|
|
|
4120
3846
|
case EN_MINORLOSS:
|
|
4121
3847
|
if (Link[index].Type != PUMP)
|
|
4122
3848
|
{
|
|
4123
|
-
if (value
|
|
3849
|
+
if (value <= 0.0) return 211;
|
|
4124
3850
|
Link[index].Km = 0.02517 * value / SQR(Link[index].Diam) /
|
|
4125
3851
|
SQR(Link[index].Diam);
|
|
4126
3852
|
}
|
|
@@ -4131,31 +3857,29 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu
|
|
|
4131
3857
|
// Cannot set status for a check valve
|
|
4132
3858
|
if (Link[index].Type == CVPIPE) return 207;
|
|
4133
3859
|
s = (char)ROUND(value);
|
|
4134
|
-
if (s < 0 || s >
|
|
4135
|
-
s = s + CLOSED;
|
|
3860
|
+
if (s < 0 || s > 1) return 211;
|
|
4136
3861
|
if (property == EN_INITSTATUS)
|
|
4137
3862
|
{
|
|
4138
|
-
Link[index].
|
|
3863
|
+
setlinkstatus(p, index, s, &Link[index].Status, &Link[index].Kc);
|
|
4139
3864
|
}
|
|
4140
3865
|
else
|
|
4141
3866
|
{
|
|
4142
|
-
setlinkstatus(p, index, s, &hyd->LinkStatus[index], &
|
|
3867
|
+
setlinkstatus(p, index, s, &hyd->LinkStatus[index], &LinkSetting[index]);
|
|
4143
3868
|
}
|
|
4144
3869
|
break;
|
|
4145
3870
|
|
|
4146
3871
|
case EN_INITSETTING:
|
|
4147
3872
|
case EN_SETTING:
|
|
3873
|
+
if (value < 0.0) return 211;
|
|
4148
3874
|
if (Link[index].Type == PIPE || Link[index].Type == CVPIPE)
|
|
4149
3875
|
{
|
|
4150
|
-
EN_setlinkvalue(p, index, EN_ROUGHNESS, value);
|
|
4151
|
-
if (property == EN_INITSETTING) Link[index].InitSetting = Link[index].Kc;
|
|
3876
|
+
return EN_setlinkvalue(p, index, EN_ROUGHNESS, value);
|
|
4152
3877
|
}
|
|
4153
3878
|
else
|
|
4154
3879
|
{
|
|
4155
3880
|
switch (Link[index].Type)
|
|
4156
3881
|
{
|
|
4157
3882
|
case PUMP:
|
|
4158
|
-
if (value < 0.0) return 211;
|
|
4159
3883
|
break;
|
|
4160
3884
|
case PRV:
|
|
4161
3885
|
case PSV:
|
|
@@ -4166,7 +3890,6 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu
|
|
|
4166
3890
|
value /= Ucf[FLOW];
|
|
4167
3891
|
break;
|
|
4168
3892
|
case TCV:
|
|
4169
|
-
case PCV:
|
|
4170
3893
|
break;
|
|
4171
3894
|
case GPV:
|
|
4172
3895
|
return 207; // Cannot modify setting for GPV
|
|
@@ -4175,13 +3898,12 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu
|
|
|
4175
3898
|
}
|
|
4176
3899
|
if (property == EN_INITSETTING)
|
|
4177
3900
|
{
|
|
4178
|
-
Link[index].Kc
|
|
4179
|
-
Link[index].InitSetting = value;
|
|
3901
|
+
setlinksetting(p, index, value, &Link[index].Status, &Link[index].Kc);
|
|
4180
3902
|
}
|
|
4181
3903
|
else
|
|
4182
3904
|
{
|
|
4183
3905
|
setlinksetting(p, index, value, &hyd->LinkStatus[index],
|
|
4184
|
-
&
|
|
3906
|
+
&LinkSetting[index]);
|
|
4185
3907
|
}
|
|
4186
3908
|
}
|
|
4187
3909
|
break;
|
|
@@ -4220,6 +3942,11 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu
|
|
|
4220
3942
|
net->Pump[pumpIndex].Ptype = CONST_HP;
|
|
4221
3943
|
net->Pump[pumpIndex].Hcurve = 0;
|
|
4222
3944
|
net->Link[index].Km = value;
|
|
3945
|
+
updatepumpparams(p, pumpIndex);
|
|
3946
|
+
net->Pump[pumpIndex].R /= Ucf[POWER];
|
|
3947
|
+
net->Pump[pumpIndex].Q0 /= Ucf[FLOW];
|
|
3948
|
+
net->Pump[pumpIndex].Qmax /= Ucf[FLOW];
|
|
3949
|
+
net->Pump[pumpIndex].Hmax /= Ucf[HEAD];
|
|
4223
3950
|
}
|
|
4224
3951
|
break;
|
|
4225
3952
|
|
|
@@ -4258,43 +3985,6 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu
|
|
|
4258
3985
|
net->Pump[pumpIndex].Epat = patIndex;
|
|
4259
3986
|
}
|
|
4260
3987
|
break;
|
|
4261
|
-
|
|
4262
|
-
case EN_PCV_CURVE:
|
|
4263
|
-
if (Link[index].Type == PCV)
|
|
4264
|
-
{
|
|
4265
|
-
curveIndex = ROUND(value);
|
|
4266
|
-
if (curveIndex < 0 || curveIndex > net->Ncurves) return 206;
|
|
4267
|
-
net->Valve[findvalve(&p->network, index)].Curve = curveIndex;
|
|
4268
|
-
}
|
|
4269
|
-
break;
|
|
4270
|
-
|
|
4271
|
-
case EN_GPV_CURVE:
|
|
4272
|
-
if (Link[index].Type == GPV)
|
|
4273
|
-
{
|
|
4274
|
-
curveIndex = ROUND(value);
|
|
4275
|
-
if (curveIndex < 0 || curveIndex > net->Ncurves) return 206;
|
|
4276
|
-
Link[index].Kc = curveIndex;
|
|
4277
|
-
if (hyd->OpenHflag == FALSE) Link[index].InitSetting = curveIndex;
|
|
4278
|
-
}
|
|
4279
|
-
break;
|
|
4280
|
-
|
|
4281
|
-
case EN_LEAK_AREA: // leak area in sq mm per 100 pipe length units
|
|
4282
|
-
if (value < 0.0) return 211;
|
|
4283
|
-
Link[index].LeakArea = value / Ucf[LENGTH];
|
|
4284
|
-
break;
|
|
4285
|
-
|
|
4286
|
-
case EN_LEAK_EXPAN: // leak area expansion slope (sq mm per unit of head)
|
|
4287
|
-
if (value < 0.0) return 211;
|
|
4288
|
-
Link[index].LeakExpan = value / Ucf[LENGTH];
|
|
4289
|
-
break;
|
|
4290
|
-
|
|
4291
|
-
case EN_VALVE_TYPE:
|
|
4292
|
-
if (hyd->OpenHflag || qual->OpenQflag) return 262; //Solver is running
|
|
4293
|
-
if (Link[index].Type <= PUMP) return 264; //Link not a valve
|
|
4294
|
-
valveType = ROUND(value);
|
|
4295
|
-
if (valveType < PRV || valveType > PCV) return 213; //Invalid valve type
|
|
4296
|
-
if (valveType == Link[index].Type) return 0; //No type change
|
|
4297
|
-
return changevalvetype(p, index, valveType); //See project.c
|
|
4298
3988
|
|
|
4299
3989
|
default:
|
|
4300
3990
|
return 251;
|
|
@@ -4353,20 +4043,20 @@ int DLLEXPORT EN_getvertexcount(EN_Project p, int index, int *count)
|
|
|
4353
4043
|
*/
|
|
4354
4044
|
{
|
|
4355
4045
|
Network *net = &p->network;
|
|
4356
|
-
|
|
4046
|
+
|
|
4357
4047
|
Slink *Link = net->Link;
|
|
4358
4048
|
Pvertices vertices;
|
|
4359
|
-
|
|
4049
|
+
|
|
4360
4050
|
// Check that link exists
|
|
4361
4051
|
*count = 0;
|
|
4362
4052
|
if (!p->Openflag) return 102;
|
|
4363
4053
|
if (index <= 0 || index > net->Nlinks) return 204;
|
|
4364
|
-
|
|
4054
|
+
|
|
4365
4055
|
// Set count to number of vertices
|
|
4366
4056
|
vertices = Link[index].Vertices;
|
|
4367
4057
|
if (vertices) *count = vertices->Npts;
|
|
4368
4058
|
return 0;
|
|
4369
|
-
}
|
|
4059
|
+
}
|
|
4370
4060
|
|
|
4371
4061
|
int DLLEXPORT EN_getvertex(EN_Project p, int index, int vertex, double *x, double *y)
|
|
4372
4062
|
/*----------------------------------------------------------------
|
|
@@ -4380,54 +4070,25 @@ int DLLEXPORT EN_getvertex(EN_Project p, int index, int vertex, double *x, doubl
|
|
|
4380
4070
|
*/
|
|
4381
4071
|
{
|
|
4382
4072
|
Network *net = &p->network;
|
|
4383
|
-
|
|
4073
|
+
|
|
4384
4074
|
Slink *Link = net->Link;
|
|
4385
4075
|
Pvertices vertices;
|
|
4386
|
-
|
|
4076
|
+
|
|
4387
4077
|
// Check that link exists
|
|
4388
4078
|
*x = MISSING;
|
|
4389
4079
|
*y = MISSING;
|
|
4390
4080
|
if (!p->Openflag) return 102;
|
|
4391
4081
|
if (index <= 0 || index > net->Nlinks) return 204;
|
|
4392
|
-
|
|
4082
|
+
|
|
4393
4083
|
// Check that vertex exists
|
|
4394
4084
|
vertices = Link[index].Vertices;
|
|
4395
4085
|
if (vertices == NULL) return 255;
|
|
4396
4086
|
if (vertex <= 0 || vertex > vertices->Npts) return 255;
|
|
4397
4087
|
*x = vertices->X[vertex - 1];
|
|
4398
|
-
*y = vertices->Y[vertex - 1];
|
|
4399
|
-
return 0;
|
|
4400
|
-
}
|
|
4401
|
-
|
|
4402
|
-
int DLLEXPORT EN_setvertex(EN_Project p, int index, int vertex, double x, double y)
|
|
4403
|
-
/*----------------------------------------------------------------
|
|
4404
|
-
** Input: index = link index
|
|
4405
|
-
** vertex = index of a link vertex point
|
|
4406
|
-
** x = vertex point's X-coordinate
|
|
4407
|
-
** y = vertex point's Y-coordinate
|
|
4408
|
-
** Returns: error code
|
|
4409
|
-
** Purpose: sets the coordinates of a vertex point in a link
|
|
4410
|
-
**----------------------------------------------------------------
|
|
4411
|
-
*/
|
|
4412
|
-
{
|
|
4413
|
-
Network *net = &p->network;
|
|
4414
|
-
|
|
4415
|
-
Slink *Link = net->Link;
|
|
4416
|
-
Pvertices vertices;
|
|
4417
|
-
|
|
4418
|
-
// Check that link exists
|
|
4419
|
-
if (!p->Openflag) return 102;
|
|
4420
|
-
if (index <= 0 || index > net->Nlinks) return 204;
|
|
4421
|
-
|
|
4422
|
-
// Check that vertex exists
|
|
4423
|
-
vertices = Link[index].Vertices;
|
|
4424
|
-
if (vertices == NULL) return 255;
|
|
4425
|
-
if (vertex <= 0 || vertex > vertices->Npts) return 255;
|
|
4426
|
-
vertices->X[vertex - 1] = x;
|
|
4427
|
-
vertices->Y[vertex - 1] = y;
|
|
4088
|
+
*y = vertices->Y[vertex - 1];
|
|
4428
4089
|
return 0;
|
|
4429
4090
|
}
|
|
4430
|
-
|
|
4091
|
+
|
|
4431
4092
|
int DLLEXPORT EN_setvertices(EN_Project p, int index, double *x, double *y, int count)
|
|
4432
4093
|
/*----------------------------------------------------------------
|
|
4433
4094
|
** Input: index = link index
|
|
@@ -4440,11 +4101,11 @@ int DLLEXPORT EN_setvertices(EN_Project p, int index, double *x, double *y, int
|
|
|
4440
4101
|
*/
|
|
4441
4102
|
{
|
|
4442
4103
|
Network *net = &p->network;
|
|
4443
|
-
|
|
4104
|
+
|
|
4444
4105
|
Slink *link;
|
|
4445
4106
|
int i;
|
|
4446
4107
|
int err = 0;
|
|
4447
|
-
|
|
4108
|
+
|
|
4448
4109
|
// Check that link exists
|
|
4449
4110
|
if (!p->Openflag) return 102;
|
|
4450
4111
|
if (index <= 0 || index > net->Nlinks) return 204;
|
|
@@ -4452,7 +4113,7 @@ int DLLEXPORT EN_setvertices(EN_Project p, int index, double *x, double *y, int
|
|
|
4452
4113
|
|
|
4453
4114
|
// Delete existing set of vertices
|
|
4454
4115
|
freelinkvertices(link);
|
|
4455
|
-
|
|
4116
|
+
|
|
4456
4117
|
// Add each new vertex to the link
|
|
4457
4118
|
for (i = 0; i < count; i++)
|
|
4458
4119
|
{
|
|
@@ -4461,7 +4122,7 @@ int DLLEXPORT EN_setvertices(EN_Project p, int index, double *x, double *y, int
|
|
|
4461
4122
|
}
|
|
4462
4123
|
if (err) freelinkvertices(link);
|
|
4463
4124
|
return err;
|
|
4464
|
-
}
|
|
4125
|
+
}
|
|
4465
4126
|
|
|
4466
4127
|
/********************************************************************
|
|
4467
4128
|
|
|
@@ -4527,7 +4188,10 @@ int DLLEXPORT EN_setheadcurveindex(EN_Project p, int linkIndex, int curveIndex)
|
|
|
4527
4188
|
{
|
|
4528
4189
|
Network *net = &p->network;
|
|
4529
4190
|
|
|
4191
|
+
double *Ucf = p->Ucf;
|
|
4530
4192
|
int pumpIndex;
|
|
4193
|
+
int oldCurveIndex;
|
|
4194
|
+
int newCurveType;
|
|
4531
4195
|
int err = 0;
|
|
4532
4196
|
Spump *pump;
|
|
4533
4197
|
|
|
@@ -4537,12 +4201,43 @@ int DLLEXPORT EN_setheadcurveindex(EN_Project p, int linkIndex, int curveIndex)
|
|
|
4537
4201
|
if (PUMP != net->Link[linkIndex].Type) return 0;
|
|
4538
4202
|
if (curveIndex < 0 || curveIndex > net->Ncurves) return 206;
|
|
4539
4203
|
|
|
4540
|
-
//
|
|
4204
|
+
// Save values that need to be restored in case new curve is invalid
|
|
4541
4205
|
pumpIndex = findpump(net, linkIndex);
|
|
4542
|
-
pump = &
|
|
4206
|
+
pump = &p->network.Pump[pumpIndex];
|
|
4207
|
+
oldCurveIndex = pump->Hcurve;
|
|
4208
|
+
newCurveType = p->network.Curve[curveIndex].Type;
|
|
4209
|
+
|
|
4210
|
+
// Assign the new curve to the pump
|
|
4211
|
+
pump->Ptype = NOCURVE;
|
|
4543
4212
|
pump->Hcurve = curveIndex;
|
|
4544
|
-
|
|
4545
|
-
|
|
4213
|
+
if (curveIndex == 0) return 0;
|
|
4214
|
+
|
|
4215
|
+
// Update the pump's head curve parameters (which also changes
|
|
4216
|
+
// the new curve's Type to PUMP_CURVE)
|
|
4217
|
+
err = updatepumpparams(p, pumpIndex);
|
|
4218
|
+
|
|
4219
|
+
// If the parameter updating failed (new curve was not a valid pump curve)
|
|
4220
|
+
// restore the pump's original curve and its parameters
|
|
4221
|
+
if (err > 0)
|
|
4222
|
+
{
|
|
4223
|
+
p->network.Curve[curveIndex].Type = newCurveType;
|
|
4224
|
+
pump->Ptype = NOCURVE;
|
|
4225
|
+
pump->Hcurve = oldCurveIndex;
|
|
4226
|
+
if (oldCurveIndex == 0) return err;
|
|
4227
|
+
updatepumpparams(p, pumpIndex);
|
|
4228
|
+
}
|
|
4229
|
+
|
|
4230
|
+
// Convert the units of the updated pump parameters to feet and cfs
|
|
4231
|
+
if (pump->Ptype == POWER_FUNC)
|
|
4232
|
+
{
|
|
4233
|
+
pump->H0 /= Ucf[HEAD];
|
|
4234
|
+
pump->R *= (pow(Ucf[FLOW], pump->N) / Ucf[HEAD]);
|
|
4235
|
+
}
|
|
4236
|
+
pump->Q0 /= Ucf[FLOW];
|
|
4237
|
+
pump->Qmax /= Ucf[FLOW];
|
|
4238
|
+
pump->Hmax /= Ucf[HEAD];
|
|
4239
|
+
|
|
4240
|
+
return err;
|
|
4546
4241
|
}
|
|
4547
4242
|
|
|
4548
4243
|
/********************************************************************
|
|
@@ -4551,7 +4246,7 @@ int DLLEXPORT EN_setheadcurveindex(EN_Project p, int linkIndex, int curveIndex)
|
|
|
4551
4246
|
|
|
4552
4247
|
********************************************************************/
|
|
4553
4248
|
|
|
4554
|
-
int DLLEXPORT EN_addpattern(EN_Project p,
|
|
4249
|
+
int DLLEXPORT EN_addpattern(EN_Project p, char *id)
|
|
4555
4250
|
/*----------------------------------------------------------------
|
|
4556
4251
|
** Input: id = time pattern ID name
|
|
4557
4252
|
** Output: none
|
|
@@ -4599,70 +4294,6 @@ int DLLEXPORT EN_addpattern(EN_Project p, const char *id)
|
|
|
4599
4294
|
return 0;
|
|
4600
4295
|
}
|
|
4601
4296
|
|
|
4602
|
-
int DLLEXPORT EN_loadpatternfile(EN_Project p, const char *filename, const char *id)
|
|
4603
|
-
/*----------------------------------------------------------------
|
|
4604
|
-
** Input: filename = name of the file containing pattern data
|
|
4605
|
-
** id = ID for the new pattern
|
|
4606
|
-
** Output: none
|
|
4607
|
-
** Returns: error code
|
|
4608
|
-
** Purpose: loads time patterns from a file into a project under a specific pattern ID
|
|
4609
|
-
**----------------------------------------------------------------
|
|
4610
|
-
*/
|
|
4611
|
-
{
|
|
4612
|
-
FILE *file;
|
|
4613
|
-
char line[MAXLINE+1];
|
|
4614
|
-
char *tok;
|
|
4615
|
-
int err = 0;
|
|
4616
|
-
int i;
|
|
4617
|
-
int len = 0;
|
|
4618
|
-
double value;
|
|
4619
|
-
double *values = NULL;
|
|
4620
|
-
int CHUNK = 50;
|
|
4621
|
-
|
|
4622
|
-
if (!p->Openflag) return 102;
|
|
4623
|
-
|
|
4624
|
-
file = fopen(filename, "r");
|
|
4625
|
-
if (file == NULL) return 302;
|
|
4626
|
-
|
|
4627
|
-
// Add a new pattern or use an existing pattern.
|
|
4628
|
-
err = EN_getpatternindex(p, id, &i);
|
|
4629
|
-
if (err == 205) {
|
|
4630
|
-
if ((err = EN_addpattern(p, id)) != 0) {
|
|
4631
|
-
fclose(file);
|
|
4632
|
-
return err;
|
|
4633
|
-
}
|
|
4634
|
-
i = p->network.Npats;
|
|
4635
|
-
}
|
|
4636
|
-
|
|
4637
|
-
// Read pattern values
|
|
4638
|
-
while (fgets(line, sizeof(line), file) != NULL) {
|
|
4639
|
-
|
|
4640
|
-
// Skip lines that don't contain valid numbers
|
|
4641
|
-
tok = strtok(line, SEPSTR);
|
|
4642
|
-
if (tok == NULL) continue;
|
|
4643
|
-
if (!getfloat(tok, &value)) continue;
|
|
4644
|
-
|
|
4645
|
-
// Resize multiplier array if it's full
|
|
4646
|
-
if (len % CHUNK == 0) {
|
|
4647
|
-
values = (double *) realloc(values, (len + CHUNK) * sizeof(double));
|
|
4648
|
-
|
|
4649
|
-
// Abort if memory allocation error
|
|
4650
|
-
if (values == NULL) {
|
|
4651
|
-
fclose(file);
|
|
4652
|
-
return 101;
|
|
4653
|
-
}
|
|
4654
|
-
}
|
|
4655
|
-
values[len] = value;
|
|
4656
|
-
len++;
|
|
4657
|
-
}
|
|
4658
|
-
fclose(file);
|
|
4659
|
-
|
|
4660
|
-
// Transfer multipliers to pattern
|
|
4661
|
-
err = EN_setpattern(p, i, values, len);
|
|
4662
|
-
free(values);
|
|
4663
|
-
return err;
|
|
4664
|
-
}
|
|
4665
|
-
|
|
4666
4297
|
int DLLEXPORT EN_deletepattern(EN_Project p, int index)
|
|
4667
4298
|
/*----------------------------------------------------------------
|
|
4668
4299
|
** Input: index = index of the pattern to delete
|
|
@@ -4692,10 +4323,6 @@ int DLLEXPORT EN_deletepattern(EN_Project p, int index)
|
|
|
4692
4323
|
if (hyd->Epat == index) hyd->Epat = 0;
|
|
4693
4324
|
else if (hyd->Epat > index) hyd->Epat--;
|
|
4694
4325
|
|
|
4695
|
-
// Modify global default demand pattern
|
|
4696
|
-
if (hyd->DefPat == index) hyd->DefPat = 0;
|
|
4697
|
-
else if (hyd->DefPat > index) hyd->DefPat--;
|
|
4698
|
-
|
|
4699
4326
|
// Free the pattern's factor array
|
|
4700
4327
|
FREE(net->Pattern[index].F);
|
|
4701
4328
|
FREE(net->Pattern[index].Comment);
|
|
@@ -4707,7 +4334,7 @@ int DLLEXPORT EN_deletepattern(EN_Project p, int index)
|
|
|
4707
4334
|
return 0;
|
|
4708
4335
|
}
|
|
4709
4336
|
|
|
4710
|
-
int DLLEXPORT EN_getpatternindex(EN_Project p,
|
|
4337
|
+
int DLLEXPORT EN_getpatternindex(EN_Project p, char *id, int *index)
|
|
4711
4338
|
/*----------------------------------------------------------------
|
|
4712
4339
|
** Input: id = time pattern name
|
|
4713
4340
|
** Output: index = time pattern index
|
|
@@ -4748,7 +4375,7 @@ int DLLEXPORT EN_getpatternid(EN_Project p, int index, char *id)
|
|
|
4748
4375
|
return 0;
|
|
4749
4376
|
}
|
|
4750
4377
|
|
|
4751
|
-
int DLLEXPORT EN_setpatternid(EN_Project p, int index,
|
|
4378
|
+
int DLLEXPORT EN_setpatternid(EN_Project p, int index, char *id)
|
|
4752
4379
|
/*----------------------------------------------------------------
|
|
4753
4380
|
** Input: index = time pattern index
|
|
4754
4381
|
** id = time pattern ID name
|
|
@@ -4845,7 +4472,7 @@ int DLLEXPORT EN_getaveragepatternvalue(EN_Project p, int index, double *value)
|
|
|
4845
4472
|
|
|
4846
4473
|
*value = 0.0;
|
|
4847
4474
|
if (!p->Openflag) return 102;
|
|
4848
|
-
if (index <
|
|
4475
|
+
if (index < 1 || index > net->Npats) return 205;
|
|
4849
4476
|
for (i = 0; i < Pattern[index].Length; i++)
|
|
4850
4477
|
{
|
|
4851
4478
|
*value += (double)Pattern[index].F[i];
|
|
@@ -4892,7 +4519,7 @@ int DLLEXPORT EN_setpattern(EN_Project p, int index, double *values, int len)
|
|
|
4892
4519
|
|
|
4893
4520
|
********************************************************************/
|
|
4894
4521
|
|
|
4895
|
-
int DLLEXPORT EN_addcurve(EN_Project p,
|
|
4522
|
+
int DLLEXPORT EN_addcurve(EN_Project p, char *id)
|
|
4896
4523
|
/*----------------------------------------------------------------
|
|
4897
4524
|
** Input: id = data curve ID name
|
|
4898
4525
|
** Output: none
|
|
@@ -4984,7 +4611,7 @@ int DLLEXPORT EN_deletecurve(EN_Project p, int index)
|
|
|
4984
4611
|
return 0;
|
|
4985
4612
|
}
|
|
4986
4613
|
|
|
4987
|
-
int DLLEXPORT EN_getcurveindex(EN_Project p,
|
|
4614
|
+
int DLLEXPORT EN_getcurveindex(EN_Project p, char *id, int *index)
|
|
4988
4615
|
/*----------------------------------------------------------------
|
|
4989
4616
|
** Input: id = data curve name
|
|
4990
4617
|
** Output: index = data curve index
|
|
@@ -5016,7 +4643,7 @@ int DLLEXPORT EN_getcurveid(EN_Project p, int index, char *id)
|
|
|
5016
4643
|
return 0;
|
|
5017
4644
|
}
|
|
5018
4645
|
|
|
5019
|
-
int DLLEXPORT EN_setcurveid(EN_Project p, int index,
|
|
4646
|
+
int DLLEXPORT EN_setcurveid(EN_Project p, int index, char *id)
|
|
5020
4647
|
/*----------------------------------------------------------------
|
|
5021
4648
|
** Input: index = data curve index
|
|
5022
4649
|
** id = data curve ID name
|
|
@@ -5072,23 +4699,6 @@ int DLLEXPORT EN_getcurvetype(EN_Project p, int index, int *type)
|
|
|
5072
4699
|
return 0;
|
|
5073
4700
|
}
|
|
5074
4701
|
|
|
5075
|
-
int DLLEXPORT EN_setcurvetype(EN_Project p, int index, int type)
|
|
5076
|
-
/*----------------------------------------------------------------
|
|
5077
|
-
** Input: index = data curve index
|
|
5078
|
-
** type = type of data curve (see EN_CurveType)
|
|
5079
|
-
** Returns: error code
|
|
5080
|
-
** Purpose: sets the type assigned to a data curve
|
|
5081
|
-
**----------------------------------------------------------------
|
|
5082
|
-
*/
|
|
5083
|
-
{
|
|
5084
|
-
Network *net = &p->network;
|
|
5085
|
-
if (!p->Openflag) return 102;
|
|
5086
|
-
if (index < 1 || index > net->Ncurves) return 206;
|
|
5087
|
-
if (type < 0 || type > EN_VALVE_CURVE) return 251;
|
|
5088
|
-
net->Curve[index].Type = type;
|
|
5089
|
-
return 0;
|
|
5090
|
-
}
|
|
5091
|
-
|
|
5092
4702
|
int DLLEXPORT EN_getcurvevalue(EN_Project p, int curveIndex, int pointIndex,
|
|
5093
4703
|
double *x, double *y)
|
|
5094
4704
|
/*----------------------------------------------------------------
|
|
@@ -5158,7 +4768,9 @@ int DLLEXPORT EN_setcurvevalue(EN_Project p, int curveIndex, int pointIndex,
|
|
|
5158
4768
|
// Insert new point into curve
|
|
5159
4769
|
curve->X[n] = x;
|
|
5160
4770
|
curve->Y[n] = y;
|
|
5161
|
-
|
|
4771
|
+
|
|
4772
|
+
// Adjust parameters for pumps using curve as a head curve
|
|
4773
|
+
return adjustpumpparams(p, curveIndex);
|
|
5162
4774
|
}
|
|
5163
4775
|
|
|
5164
4776
|
int DLLEXPORT EN_getcurve(EN_Project p, int index, char *id, int *nPoints,
|
|
@@ -5230,7 +4842,9 @@ int DLLEXPORT EN_setcurve(EN_Project p, int index, double *xValues,
|
|
|
5230
4842
|
curve->X[j] = xValues[j];
|
|
5231
4843
|
curve->Y[j] = yValues[j];
|
|
5232
4844
|
}
|
|
5233
|
-
|
|
4845
|
+
|
|
4846
|
+
// Adjust parameters for pumps using curve as a head curve
|
|
4847
|
+
return adjustpumpparams(p, index);
|
|
5234
4848
|
}
|
|
5235
4849
|
|
|
5236
4850
|
/********************************************************************
|
|
@@ -5256,30 +4870,84 @@ int DLLEXPORT EN_addcontrol(EN_Project p, int type, int linkIndex, double settin
|
|
|
5256
4870
|
*/
|
|
5257
4871
|
{
|
|
5258
4872
|
Network *net = &p->network;
|
|
4873
|
+
Parser *parser = &p->parser;
|
|
4874
|
+
|
|
4875
|
+
char status = ACTIVE;
|
|
4876
|
+
int n;
|
|
4877
|
+
long t = 0;
|
|
4878
|
+
double s = setting, lvl = level;
|
|
4879
|
+
double *Ucf = p->Ucf;
|
|
4880
|
+
Scontrol *control;
|
|
5259
4881
|
|
|
5260
|
-
int err, n;
|
|
5261
|
-
Scontrol ctrl;
|
|
5262
4882
|
|
|
5263
4883
|
// Check that project exists
|
|
5264
4884
|
if (!p->Openflag) return 102;
|
|
5265
4885
|
|
|
5266
4886
|
// Check that controlled link exists
|
|
5267
4887
|
if (linkIndex <= 0 || linkIndex > net->Nlinks) return 204;
|
|
5268
|
-
|
|
5269
|
-
//
|
|
5270
|
-
|
|
5271
|
-
|
|
4888
|
+
|
|
4889
|
+
// Cannot control check valve
|
|
4890
|
+
if (net->Link[linkIndex].Type == CVPIPE) return 207;
|
|
4891
|
+
|
|
4892
|
+
// Check for valid parameters
|
|
4893
|
+
if (type < 0 || type > EN_TIMEOFDAY) return 251;
|
|
4894
|
+
if (type == EN_LOWLEVEL || type == EN_HILEVEL)
|
|
4895
|
+
{
|
|
4896
|
+
if (nodeIndex < 1 || nodeIndex > net->Nnodes) return 203;
|
|
4897
|
+
}
|
|
4898
|
+
else nodeIndex = 0;
|
|
4899
|
+
if (s < 0.0 || lvl < 0.0) return 202;
|
|
4900
|
+
|
|
4901
|
+
// Adjust units of control parameters
|
|
4902
|
+
switch (net->Link[linkIndex].Type)
|
|
4903
|
+
{
|
|
4904
|
+
case PRV:
|
|
4905
|
+
case PSV:
|
|
4906
|
+
case PBV:
|
|
4907
|
+
s /= Ucf[PRESSURE];
|
|
4908
|
+
break;
|
|
4909
|
+
case FCV:
|
|
4910
|
+
s /= Ucf[FLOW];
|
|
4911
|
+
break;
|
|
4912
|
+
case GPV:
|
|
4913
|
+
if (s == 0.0) status = CLOSED;
|
|
4914
|
+
else if (s == 1.0) status = OPEN;
|
|
4915
|
+
else return 202;
|
|
4916
|
+
s = net->Link[linkIndex].Kc;
|
|
4917
|
+
break;
|
|
4918
|
+
case PIPE:
|
|
4919
|
+
case PUMP:
|
|
4920
|
+
status = OPEN;
|
|
4921
|
+
if (s == 0.0) status = CLOSED;
|
|
4922
|
+
default:
|
|
4923
|
+
break;
|
|
4924
|
+
}
|
|
4925
|
+
|
|
4926
|
+
if (type == LOWLEVEL || type == HILEVEL)
|
|
4927
|
+
{
|
|
4928
|
+
if (nodeIndex > net->Njuncs) lvl = net->Node[nodeIndex].El + level / Ucf[ELEV];
|
|
4929
|
+
else lvl = net->Node[nodeIndex].El + level / Ucf[PRESSURE];
|
|
4930
|
+
}
|
|
4931
|
+
if (type == TIMER) t = (long)ROUND(lvl);
|
|
4932
|
+
if (type == TIMEOFDAY) t = (long)ROUND(lvl) % SECperDAY;
|
|
5272
4933
|
|
|
5273
4934
|
// Expand project's array of controls
|
|
5274
4935
|
n = net->Ncontrols + 1;
|
|
5275
4936
|
net->Control = (Scontrol *)realloc(net->Control, (n + 1) * sizeof(Scontrol));
|
|
5276
4937
|
|
|
5277
4938
|
// Set properties of the new control
|
|
5278
|
-
net->Control[n]
|
|
4939
|
+
control = &net->Control[n];
|
|
4940
|
+
control->Type = (char)type;
|
|
4941
|
+
control->Link = linkIndex;
|
|
4942
|
+
control->Node = nodeIndex;
|
|
4943
|
+
control->Status = status;
|
|
4944
|
+
control->Setting = s;
|
|
4945
|
+
control->Grade = lvl;
|
|
4946
|
+
control->Time = t;
|
|
5279
4947
|
|
|
5280
4948
|
// Update number of controls
|
|
5281
4949
|
net->Ncontrols = n;
|
|
5282
|
-
|
|
4950
|
+
parser->MaxControls = n;
|
|
5283
4951
|
|
|
5284
4952
|
// Replace the control's index
|
|
5285
4953
|
*index = n;
|
|
@@ -5362,8 +5030,8 @@ int DLLEXPORT EN_getcontrol(EN_Project p, int index, int *type, int *linkIndex,
|
|
|
5362
5030
|
break;
|
|
5363
5031
|
}
|
|
5364
5032
|
}
|
|
5365
|
-
else if (control->Status == OPEN) s =
|
|
5366
|
-
else s =
|
|
5033
|
+
else if (control->Status == OPEN) s = 1.0;
|
|
5034
|
+
else s = 0.0;
|
|
5367
5035
|
|
|
5368
5036
|
// Retrieve level value for a node level control
|
|
5369
5037
|
*nodeIndex = control->Node;
|
|
@@ -5385,8 +5053,8 @@ int DLLEXPORT EN_getcontrol(EN_Project p, int index, int *type, int *linkIndex,
|
|
|
5385
5053
|
{
|
|
5386
5054
|
lvl = (double)control->Time;
|
|
5387
5055
|
}
|
|
5388
|
-
*setting = s;
|
|
5389
|
-
*level = lvl;
|
|
5056
|
+
*setting = (double)s;
|
|
5057
|
+
*level = (double)lvl;
|
|
5390
5058
|
return 0;
|
|
5391
5059
|
}
|
|
5392
5060
|
|
|
@@ -5408,63 +5076,81 @@ int DLLEXPORT EN_setcontrol(EN_Project p, int index, int type, int linkIndex,
|
|
|
5408
5076
|
{
|
|
5409
5077
|
Network *net = &p->network;
|
|
5410
5078
|
|
|
5411
|
-
|
|
5412
|
-
|
|
5079
|
+
char status = ACTIVE;
|
|
5080
|
+
long t = 0;
|
|
5081
|
+
double s = setting, lvl = level;
|
|
5082
|
+
double *Ucf = p->Ucf;
|
|
5083
|
+
Slink *link;
|
|
5084
|
+
Scontrol *control;
|
|
5413
5085
|
|
|
5414
5086
|
// Check that project exists
|
|
5415
5087
|
if (!p->Openflag) return 102;
|
|
5416
5088
|
|
|
5417
5089
|
// Check that control exists
|
|
5418
5090
|
if (index <= 0 || index > net->Ncontrols) return 241;
|
|
5091
|
+
control = &net->Control[index];
|
|
5419
5092
|
|
|
5420
5093
|
// Check that controlled link exists (0 index de-activates the control)
|
|
5421
5094
|
if (linkIndex == 0)
|
|
5422
5095
|
{
|
|
5423
|
-
|
|
5096
|
+
control->Link = 0;
|
|
5424
5097
|
return 0;
|
|
5425
5098
|
}
|
|
5426
5099
|
if (linkIndex < 0 || linkIndex > net->Nlinks) return 204;
|
|
5427
5100
|
|
|
5428
|
-
//
|
|
5429
|
-
|
|
5430
|
-
if (err > 0) return err;
|
|
5431
|
-
net->Control[index] = ctrl;
|
|
5432
|
-
return 0;
|
|
5433
|
-
}
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
int DLLEXPORT EN_getcontrolenabled(EN_Project p, int index, int *enabled)
|
|
5437
|
-
{
|
|
5438
|
-
Network *net = &p->network;
|
|
5439
|
-
Scontrol *control;
|
|
5440
|
-
|
|
5441
|
-
// Check for valid arguments
|
|
5442
|
-
if (!p->Openflag)
|
|
5443
|
-
return 102;
|
|
5444
|
-
if (index <= 0 || index > net->Ncontrols)
|
|
5445
|
-
return 241;
|
|
5446
|
-
|
|
5447
|
-
control = &net->Control[index];
|
|
5448
|
-
*enabled = control->isEnabled;
|
|
5449
|
-
return 0;
|
|
5450
|
-
}
|
|
5101
|
+
// Cannot control check valve
|
|
5102
|
+
if (net->Link[linkIndex].Type == CVPIPE) return 207;
|
|
5451
5103
|
|
|
5104
|
+
// Check for valid control properties
|
|
5105
|
+
if (type < 0 || type > EN_TIMEOFDAY) return 251;
|
|
5106
|
+
if (type == EN_LOWLEVEL || type == EN_HILEVEL)
|
|
5107
|
+
{
|
|
5108
|
+
if (nodeIndex < 1 || nodeIndex > net->Nnodes) return 203;
|
|
5109
|
+
}
|
|
5110
|
+
else nodeIndex = 0;
|
|
5111
|
+
if (s < 0.0 || lvl < 0.0) return 202;
|
|
5452
5112
|
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5113
|
+
// Adjust units of control's properties
|
|
5114
|
+
link = &net->Link[linkIndex];
|
|
5115
|
+
switch (link->Type)
|
|
5116
|
+
{
|
|
5117
|
+
case PRV:
|
|
5118
|
+
case PSV:
|
|
5119
|
+
case PBV:
|
|
5120
|
+
s /= Ucf[PRESSURE];
|
|
5121
|
+
break;
|
|
5122
|
+
case FCV:
|
|
5123
|
+
s /= Ucf[FLOW];
|
|
5124
|
+
break;
|
|
5125
|
+
case GPV:
|
|
5126
|
+
if (s == 0.0) status = CLOSED;
|
|
5127
|
+
else if (s == 1.0) status = OPEN;
|
|
5128
|
+
else return 202;
|
|
5129
|
+
s = link->Kc;
|
|
5130
|
+
break;
|
|
5131
|
+
case PIPE:
|
|
5132
|
+
case PUMP:
|
|
5133
|
+
status = OPEN;
|
|
5134
|
+
if (s == 0.0) status = CLOSED;
|
|
5135
|
+
default:
|
|
5136
|
+
break;
|
|
5137
|
+
}
|
|
5138
|
+
if (type == LOWLEVEL || type == HILEVEL)
|
|
5139
|
+
{
|
|
5140
|
+
if (nodeIndex > net->Njuncs) lvl = net->Node[nodeIndex].El + level / Ucf[ELEV];
|
|
5141
|
+
else lvl = net->Node[nodeIndex].El + level / Ucf[PRESSURE];
|
|
5142
|
+
}
|
|
5143
|
+
if (type == TIMER) t = (long)ROUND(lvl);
|
|
5144
|
+
if (type == TIMEOFDAY) t = (long)ROUND(lvl) % SECperDAY;
|
|
5145
|
+
|
|
5146
|
+
/* Reset control's parameters */
|
|
5147
|
+
control->Type = (char)type;
|
|
5148
|
+
control->Link = linkIndex;
|
|
5149
|
+
control->Node = nodeIndex;
|
|
5150
|
+
control->Status = status;
|
|
5151
|
+
control->Setting = s;
|
|
5152
|
+
control->Grade = lvl;
|
|
5153
|
+
control->Time = t;
|
|
5468
5154
|
return 0;
|
|
5469
5155
|
}
|
|
5470
5156
|
|
|
@@ -5718,7 +5404,7 @@ int DLLEXPORT EN_setpremisestatus(EN_Project p, int ruleIndex, int premiseIndex,
|
|
|
5718
5404
|
** Input: ruleIndex = rule index
|
|
5719
5405
|
** premiseIndex = premise index
|
|
5720
5406
|
** status = object status being tested against
|
|
5721
|
-
** (see EN_RuleStatus)
|
|
5407
|
+
** (see EN_RuleStatus))
|
|
5722
5408
|
** Output: none
|
|
5723
5409
|
** Returns: error code
|
|
5724
5410
|
** Purpose: sets the status of an object being tested against
|
|
@@ -5770,7 +5456,7 @@ int DLLEXPORT EN_getthenaction(EN_Project p, int ruleIndex, int actionIndex,
|
|
|
5770
5456
|
** Input: ruleIndex = rule index
|
|
5771
5457
|
** actionIndex = index of a rule's THEN actions
|
|
5772
5458
|
** Output: linkIndex = index of link appearing in the action
|
|
5773
|
-
** status = status assigned to the link (see EN_RuleStatus)
|
|
5459
|
+
** status = status assigned to the link (see EN_RuleStatus))
|
|
5774
5460
|
** setting = setting assigned to the link
|
|
5775
5461
|
** Returns: error code
|
|
5776
5462
|
** Purpose: retrieves the properties of a rule's THEN action
|
|
@@ -5798,7 +5484,7 @@ int DLLEXPORT EN_setthenaction(EN_Project p, int ruleIndex, int actionIndex,
|
|
|
5798
5484
|
** Input: ruleIndex = rule index
|
|
5799
5485
|
** actionIndex = index of a rule's THEN actions
|
|
5800
5486
|
** linkIndex = index of link appearing in the action
|
|
5801
|
-
** status = status assigned to the link (see EN_RuleStatus)
|
|
5487
|
+
** status = status assigned to the link (see EN_RuleStatus))
|
|
5802
5488
|
** setting = setting assigned to the link
|
|
5803
5489
|
** Returns: error code
|
|
5804
5490
|
** Purpose: sets the properties of a rule's THEN action
|
|
@@ -5826,7 +5512,7 @@ int DLLEXPORT EN_getelseaction(EN_Project p, int ruleIndex, int actionIndex,
|
|
|
5826
5512
|
** Input: ruleIndex = rule index
|
|
5827
5513
|
** actionIndex = index of a rule's ELSE actions
|
|
5828
5514
|
** Output: linkIndex = index of link appearing in the action
|
|
5829
|
-
** status = status assigned to the link (see EN_RuleStatus)
|
|
5515
|
+
** status = status assigned to the link (see EN_RuleStatus))
|
|
5830
5516
|
** setting = setting assigned to the link
|
|
5831
5517
|
** Returns: error code
|
|
5832
5518
|
** Purpose: retrieves the properties of a rule's ELSE action
|
|
@@ -5854,7 +5540,7 @@ int DLLEXPORT EN_setelseaction(EN_Project p, int ruleIndex, int actionIndex,
|
|
|
5854
5540
|
** Input: ruleIndex = rule index
|
|
5855
5541
|
** actionIndex = index of a rule's ELSE actions
|
|
5856
5542
|
** linkIndex = index of link appearing in the action
|
|
5857
|
-
** status = status assigned to the link (see EN_RuleStatus)
|
|
5543
|
+
** status = status assigned to the link (see EN_RuleStatus))
|
|
5858
5544
|
** setting = setting assigned to the link
|
|
5859
5545
|
** Returns: error code
|
|
5860
5546
|
** Purpose: sets the properties of a rule's ELSE action
|
|
@@ -5890,41 +5576,3 @@ int DLLEXPORT EN_setrulepriority(EN_Project p, int index, double priority)
|
|
|
5890
5576
|
p->network.Rule[index].priority = priority;
|
|
5891
5577
|
return 0;
|
|
5892
5578
|
}
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
int DLLEXPORT EN_getruleenabled(EN_Project p, int index, int *enabled)
|
|
5896
|
-
{
|
|
5897
|
-
Network *net = &p->network;
|
|
5898
|
-
Srule *rule;
|
|
5899
|
-
|
|
5900
|
-
// Check for valid arguments
|
|
5901
|
-
if (!p->Openflag)
|
|
5902
|
-
return 102;
|
|
5903
|
-
if (index <= 0 || index > net->Nrules)
|
|
5904
|
-
return 241;
|
|
5905
|
-
|
|
5906
|
-
rule = &net->Rule[index];
|
|
5907
|
-
*enabled = rule->isEnabled;
|
|
5908
|
-
return 0;
|
|
5909
|
-
}
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
int DLLEXPORT EN_setruleenabled(EN_Project p, int index, int enabled)
|
|
5913
|
-
{
|
|
5914
|
-
Network *net = &p->network;
|
|
5915
|
-
Srule *rule;
|
|
5916
|
-
|
|
5917
|
-
// Check for valid arguments
|
|
5918
|
-
if (enabled != TRUE && enabled != FALSE)
|
|
5919
|
-
return 202; // illegal numeric value
|
|
5920
|
-
if (!p->Openflag)
|
|
5921
|
-
return 102;
|
|
5922
|
-
if (index <= 0 || index > net->Nrules)
|
|
5923
|
-
return 241;
|
|
5924
|
-
|
|
5925
|
-
rule = &net->Rule[index];
|
|
5926
|
-
rule->isEnabled = enabled;
|
|
5927
|
-
return 0;
|
|
5928
|
-
}
|
|
5929
|
-
|
|
5930
|
-
|