epyt-flow 0.14.0__py3-none-any.whl → 0.14.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS +40 -8
- epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +3 -3
- epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +24 -7
- epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +726 -374
- epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +128 -32
- epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +7 -1
- epyt_flow/EPANET/EPANET/SRC_engines/flowbalance.c +186 -0
- epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +40 -14
- epyt_flow/EPANET/EPANET/SRC_engines/hash.c +177 -177
- epyt_flow/EPANET/EPANET/SRC_engines/hash.h +28 -28
- epyt_flow/EPANET/EPANET/SRC_engines/hydcoeffs.c +192 -40
- epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +101 -46
- epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +85 -24
- epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +29 -63
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +70 -37
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +408 -234
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +87 -37
- epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +153 -79
- epyt_flow/EPANET/EPANET/SRC_engines/input1.c +59 -94
- epyt_flow/EPANET/EPANET/SRC_engines/input2.c +73 -202
- epyt_flow/EPANET/EPANET/SRC_engines/input3.c +446 -351
- epyt_flow/EPANET/EPANET/SRC_engines/leakage.c +527 -0
- epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +8 -4
- epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +23 -23
- epyt_flow/EPANET/EPANET/SRC_engines/output.c +5 -4
- epyt_flow/EPANET/EPANET/SRC_engines/project.c +407 -75
- epyt_flow/EPANET/EPANET/SRC_engines/quality.c +12 -2
- epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +70 -13
- epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +7 -5
- epyt_flow/EPANET/EPANET/SRC_engines/report.c +88 -20
- epyt_flow/EPANET/EPANET/SRC_engines/rules.c +144 -6
- epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +19 -19
- epyt_flow/EPANET/EPANET/SRC_engines/text.h +16 -5
- epyt_flow/EPANET/EPANET/SRC_engines/types.h +73 -19
- epyt_flow/EPANET/EPANET/SRC_engines/util/cstr_helper.c +59 -0
- epyt_flow/EPANET/EPANET/SRC_engines/util/cstr_helper.h +38 -0
- epyt_flow/EPANET/EPANET/SRC_engines/util/errormanager.c +92 -0
- epyt_flow/EPANET/EPANET/SRC_engines/util/errormanager.h +39 -0
- epyt_flow/EPANET/EPANET/SRC_engines/util/filemanager.c +212 -0
- epyt_flow/EPANET/EPANET/SRC_engines/util/filemanager.h +81 -0
- epyt_flow/EPANET/EPANET/SRC_engines/validate.c +408 -0
- epyt_flow/EPANET/compile_linux.sh +1 -1
- epyt_flow/EPANET/compile_macos.sh +1 -1
- epyt_flow/VERSION +1 -1
- epyt_flow/gym/scenario_control_env.py +26 -3
- epyt_flow/simulation/events/quality_events.py +6 -6
- epyt_flow/simulation/events/sensor_faults.py +24 -24
- epyt_flow/simulation/events/system_event.py +3 -3
- epyt_flow/simulation/scada/scada_data.py +1 -1
- epyt_flow/simulation/scenario_simulator.py +14 -11
- epyt_flow/topology.py +8 -1
- epyt_flow/uncertainty/model_uncertainty.py +292 -150
- {epyt_flow-0.14.0.dist-info → epyt_flow-0.14.1.dist-info}/METADATA +2 -2
- {epyt_flow-0.14.0.dist-info → epyt_flow-0.14.1.dist-info}/RECORD +57 -51
- epyt_flow/EPANET/EPANET/SRC_engines/Readme_SRC_Engines.txt +0 -18
- epyt_flow/EPANET/EPANET/SRC_engines/epanet2.def +0 -131
- epyt_flow/EPANET/EPANET/SRC_engines/main.c +0 -93
- {epyt_flow-0.14.0.dist-info → epyt_flow-0.14.1.dist-info}/WHEEL +0 -0
- {epyt_flow-0.14.0.dist-info → epyt_flow-0.14.1.dist-info}/licenses/LICENSE +0 -0
- {epyt_flow-0.14.0.dist-info → epyt_flow-0.14.1.dist-info}/top_level.txt +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/*
|
|
2
2
|
******************************************************************************
|
|
3
3
|
Project: OWA EPANET
|
|
4
|
-
Version: 2.
|
|
4
|
+
Version: 2.3
|
|
5
5
|
Module: 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: 04/23/2025
|
|
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 > CMS) return 251;
|
|
147
147
|
if (headLossType < 0 || headLossType > CM) return 251;
|
|
148
148
|
|
|
149
149
|
// Open files
|
|
@@ -179,61 +179,29 @@ 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:
|
|
182
|
+
** Purpose: reads an EPANET input file with no errors allowed.
|
|
183
183
|
**----------------------------------------------------------------
|
|
184
184
|
*/
|
|
185
|
-
{
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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));
|
|
185
|
+
{
|
|
186
|
+
writewin(p->viewprog, FMT100);
|
|
187
|
+
return openproject(p, inpFile, rptFile, outFile, FALSE);
|
|
188
|
+
}
|
|
226
189
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
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.
|
|
199
|
+
**----------------------------------------------------------------
|
|
200
|
+
*/
|
|
201
|
+
{
|
|
202
|
+
writewin(p->viewprog, FMT100);
|
|
203
|
+
return openproject(p, inpFile, rptFile, outFile, TRUE);
|
|
204
|
+
}
|
|
237
205
|
|
|
238
206
|
int DLLEXPORT EN_gettitle(EN_Project p, char *line1, char *line2, char *line3)
|
|
239
207
|
/*----------------------------------------------------------------
|
|
@@ -251,7 +219,8 @@ int DLLEXPORT EN_gettitle(EN_Project p, char *line1, char *line2, char *line3)
|
|
|
251
219
|
return 0;
|
|
252
220
|
}
|
|
253
221
|
|
|
254
|
-
int DLLEXPORT EN_settitle(EN_Project p, char *line1,
|
|
222
|
+
int DLLEXPORT EN_settitle(EN_Project p, const char *line1,
|
|
223
|
+
const char *line2, const char *line3)
|
|
255
224
|
/*----------------------------------------------------------------
|
|
256
225
|
** Input: line1, line2, line3 = project's title lines
|
|
257
226
|
** Returns: error code
|
|
@@ -279,7 +248,8 @@ int DLLEXPORT EN_getcomment(EN_Project p, int object, int index, char *comment)
|
|
|
279
248
|
return getcomment(&p->network, object, index, comment);
|
|
280
249
|
}
|
|
281
250
|
|
|
282
|
-
int DLLEXPORT EN_setcomment(EN_Project p, int object, int index,
|
|
251
|
+
int DLLEXPORT EN_setcomment(EN_Project p, int object, int index,
|
|
252
|
+
const char *comment)
|
|
283
253
|
/*----------------------------------------------------------------
|
|
284
254
|
** Input: object = a type of object (see EN_ObjectType)
|
|
285
255
|
** index = the object's index
|
|
@@ -292,6 +262,32 @@ int DLLEXPORT EN_setcomment(EN_Project p, int object, int index, char *comment)
|
|
|
292
262
|
return setcomment(&p->network, object, index, comment);
|
|
293
263
|
}
|
|
294
264
|
|
|
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
|
+
}
|
|
295
291
|
int DLLEXPORT EN_getcount(EN_Project p, int object, int *count)
|
|
296
292
|
/*----------------------------------------------------------------
|
|
297
293
|
** Input: object = type of object to count (see EN_CountType)
|
|
@@ -357,7 +353,6 @@ int DLLEXPORT EN_close(EN_Project p)
|
|
|
357
353
|
*/
|
|
358
354
|
{
|
|
359
355
|
// Free all project data
|
|
360
|
-
if (p->Openflag) writetime(p, FMT105);
|
|
361
356
|
freedata(p);
|
|
362
357
|
|
|
363
358
|
// Close output file
|
|
@@ -493,7 +488,11 @@ int DLLEXPORT EN_openH(EN_Project p)
|
|
|
493
488
|
|
|
494
489
|
// Open hydraulics solver
|
|
495
490
|
ERRCODE(openhyd(p));
|
|
496
|
-
if (!errcode)
|
|
491
|
+
if (!errcode)
|
|
492
|
+
{
|
|
493
|
+
p->hydraul.OpenHflag = TRUE;
|
|
494
|
+
writetime(p, FMT104);
|
|
495
|
+
}
|
|
497
496
|
else errmsg(p, errcode);
|
|
498
497
|
return errcode;
|
|
499
498
|
}
|
|
@@ -536,6 +535,10 @@ int DLLEXPORT EN_initH(EN_Project p, int initFlag)
|
|
|
536
535
|
return errcode;
|
|
537
536
|
}
|
|
538
537
|
}
|
|
538
|
+
|
|
539
|
+
// Open pipe leakage modeling system
|
|
540
|
+
errcode = openleakage(p);
|
|
541
|
+
if (errcode) return errcode;
|
|
539
542
|
|
|
540
543
|
// Initialize hydraulics solver
|
|
541
544
|
inithyd(p, fflag);
|
|
@@ -590,7 +593,11 @@ int DLLEXPORT EN_closeH(EN_Project p)
|
|
|
590
593
|
*/
|
|
591
594
|
{
|
|
592
595
|
if (!p->Openflag) return 102;
|
|
593
|
-
if (p->hydraul.OpenHflag)
|
|
596
|
+
if (p->hydraul.OpenHflag)
|
|
597
|
+
{
|
|
598
|
+
closeleakage(p);
|
|
599
|
+
closehyd(p);
|
|
600
|
+
}
|
|
594
601
|
p->hydraul.OpenHflag = FALSE;
|
|
595
602
|
return 0;
|
|
596
603
|
}
|
|
@@ -832,6 +839,7 @@ int DLLEXPORT EN_closeQ(EN_Project p)
|
|
|
832
839
|
closequal(p);
|
|
833
840
|
p->quality.OpenQflag = FALSE;
|
|
834
841
|
closeoutfile(p);
|
|
842
|
+
writetime(p, FMT105);
|
|
835
843
|
return 0;
|
|
836
844
|
}
|
|
837
845
|
|
|
@@ -841,7 +849,35 @@ int DLLEXPORT EN_closeQ(EN_Project p)
|
|
|
841
849
|
|
|
842
850
|
********************************************************************/
|
|
843
851
|
|
|
844
|
-
|
|
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)
|
|
845
881
|
/*----------------------------------------------------------------
|
|
846
882
|
** Input: line = line of text
|
|
847
883
|
** Output: none
|
|
@@ -877,7 +913,7 @@ int DLLEXPORT EN_report(EN_Project p)
|
|
|
877
913
|
return errcode;
|
|
878
914
|
}
|
|
879
915
|
|
|
880
|
-
int DLLEXPORT EN_copyreport(EN_Project p, char *filename)
|
|
916
|
+
int DLLEXPORT EN_copyreport(EN_Project p, const char *filename)
|
|
881
917
|
/*----------------------------------------------------------------
|
|
882
918
|
** Input: filename = name of file to receive copy of report
|
|
883
919
|
** Output: none
|
|
@@ -926,7 +962,7 @@ int DLLEXPORT EN_resetreport(EN_Project p)
|
|
|
926
962
|
return 0;
|
|
927
963
|
}
|
|
928
964
|
|
|
929
|
-
int DLLEXPORT EN_setreport(EN_Project p, char *format)
|
|
965
|
+
int DLLEXPORT EN_setreport(EN_Project p, const char *format)
|
|
930
966
|
/*----------------------------------------------------------------
|
|
931
967
|
** Input: format = a report formatting command
|
|
932
968
|
** Output: none
|
|
@@ -983,7 +1019,7 @@ int DLLEXPORT EN_getversion(int *version)
|
|
|
983
1019
|
|
|
984
1020
|
int DLLEXPORT EN_geterror(int errcode, char *errmsg, int maxLen)
|
|
985
1021
|
/*----------------------------------------------------------------
|
|
986
|
-
** Input: errcode = an error or
|
|
1022
|
+
** Input: errcode = an error or warning code
|
|
987
1023
|
** maxLen = maximum characters that errmsg can hold
|
|
988
1024
|
** Output: errmsg = text of error/warning message
|
|
989
1025
|
** Returns: error code
|
|
@@ -1056,6 +1092,9 @@ int DLLEXPORT EN_getstatistic(EN_Project p, int type, double *value)
|
|
|
1056
1092
|
case EN_DEMANDREDUCTION:
|
|
1057
1093
|
*value = p->hydraul.DemandReduction;
|
|
1058
1094
|
break;
|
|
1095
|
+
case EN_LEAKAGELOSS:
|
|
1096
|
+
*value = p->hydraul.LeakageLoss;
|
|
1097
|
+
break;
|
|
1059
1098
|
case EN_MASSBALANCE:
|
|
1060
1099
|
*value = p->quality.MassBalance.ratio;
|
|
1061
1100
|
break;
|
|
@@ -1187,7 +1226,18 @@ int DLLEXPORT EN_getoption(EN_Project p, int option, double *value)
|
|
|
1187
1226
|
case EN_CONCENLIMIT:
|
|
1188
1227
|
v = qual->Climit * p->Ucf[QUALITY];
|
|
1189
1228
|
break;
|
|
1190
|
-
|
|
1229
|
+
case EN_DEMANDPATTERN:
|
|
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;
|
|
1191
1241
|
default:
|
|
1192
1242
|
return 251;
|
|
1193
1243
|
}
|
|
@@ -1211,9 +1261,12 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
|
|
|
1211
1261
|
|
|
1212
1262
|
int Njuncs = net->Njuncs;
|
|
1213
1263
|
double *Ucf = p->Ucf;
|
|
1214
|
-
int i, j, pat;
|
|
1264
|
+
int i, j, pat, unit;
|
|
1215
1265
|
double Ke, n, ucf;
|
|
1216
1266
|
|
|
1267
|
+
double qfactor, hfactor, pfactor, dfactor;
|
|
1268
|
+
double dcf, pcf, hcf, qcf;
|
|
1269
|
+
|
|
1217
1270
|
if (!p->Openflag) return 102;
|
|
1218
1271
|
|
|
1219
1272
|
// The EN_UNBALANCED option can be < 0 indicating that the simulation
|
|
@@ -1230,7 +1283,7 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
|
|
|
1230
1283
|
// All other option values must be non-negative
|
|
1231
1284
|
if (value < 0.0) return 213;
|
|
1232
1285
|
|
|
1233
|
-
// Process the
|
|
1286
|
+
// Process the specified option
|
|
1234
1287
|
switch (option)
|
|
1235
1288
|
{
|
|
1236
1289
|
case EN_TRIALS:
|
|
@@ -1302,7 +1355,12 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
|
|
|
1302
1355
|
|
|
1303
1356
|
case EN_SP_GRAVITY:
|
|
1304
1357
|
if (value <= 0.0) return 213;
|
|
1305
|
-
|
|
1358
|
+
if (p->parser.Pressflag == PSI ||
|
|
1359
|
+
p->parser.Pressflag == KPA ||
|
|
1360
|
+
p->parser.Pressflag == BAR)
|
|
1361
|
+
{
|
|
1362
|
+
Ucf[PRESSURE] *= (value / hyd->SpGrav);
|
|
1363
|
+
}
|
|
1306
1364
|
hyd->SpGrav = value;
|
|
1307
1365
|
break;
|
|
1308
1366
|
|
|
@@ -1344,6 +1402,42 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
|
|
|
1344
1402
|
qual->Climit = value / p->Ucf[QUALITY];
|
|
1345
1403
|
break;
|
|
1346
1404
|
|
|
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
|
+
|
|
1347
1441
|
default:
|
|
1348
1442
|
return 251;
|
|
1349
1443
|
}
|
|
@@ -1376,8 +1470,9 @@ int DLLEXPORT EN_setflowunits(EN_Project p, int units)
|
|
|
1376
1470
|
{
|
|
1377
1471
|
Network *net = &p->network;
|
|
1378
1472
|
|
|
1379
|
-
int i, j;
|
|
1380
|
-
double qfactor, vfactor, hfactor, efactor, xfactor, yfactor;
|
|
1473
|
+
int i, j, oldUnitFlag;
|
|
1474
|
+
double qfactor, vfactor, hfactor, efactor, pfactor, dfactor, xfactor, yfactor;
|
|
1475
|
+
double dcf, pcf, hcf, qcf;
|
|
1381
1476
|
double *Ucf = p->Ucf;
|
|
1382
1477
|
|
|
1383
1478
|
if (!p->Openflag) return 102;
|
|
@@ -1387,7 +1482,10 @@ int DLLEXPORT EN_setflowunits(EN_Project p, int units)
|
|
|
1387
1482
|
vfactor = Ucf[VOLUME];
|
|
1388
1483
|
hfactor = Ucf[HEAD];
|
|
1389
1484
|
efactor = Ucf[ELEV];
|
|
1485
|
+
pfactor = Ucf[PRESSURE];
|
|
1486
|
+
dfactor = Ucf[DEMAND];
|
|
1390
1487
|
|
|
1488
|
+
oldUnitFlag = p->parser.Unitsflag;
|
|
1391
1489
|
p->parser.Flowflag = units;
|
|
1392
1490
|
switch (units)
|
|
1393
1491
|
{
|
|
@@ -1396,6 +1494,7 @@ int DLLEXPORT EN_setflowunits(EN_Project p, int units)
|
|
|
1396
1494
|
case MLD:
|
|
1397
1495
|
case CMH:
|
|
1398
1496
|
case CMD:
|
|
1497
|
+
case CMS:
|
|
1399
1498
|
p->parser.Unitsflag = SI;
|
|
1400
1499
|
break;
|
|
1401
1500
|
default:
|
|
@@ -1404,10 +1503,20 @@ int DLLEXPORT EN_setflowunits(EN_Project p, int units)
|
|
|
1404
1503
|
}
|
|
1405
1504
|
|
|
1406
1505
|
// Revise pressure units depending on flow units
|
|
1407
|
-
if (
|
|
1408
|
-
|
|
1506
|
+
if (oldUnitFlag != p->parser.Unitsflag)
|
|
1507
|
+
{
|
|
1508
|
+
if (p->parser.Unitsflag == US) p->parser.Pressflag = PSI;
|
|
1509
|
+
else p->parser.Pressflag = METERS;
|
|
1510
|
+
}
|
|
1409
1511
|
initunits(p);
|
|
1410
1512
|
|
|
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
|
+
|
|
1411
1520
|
//update curves
|
|
1412
1521
|
for (i = 1; i <= net->Ncurves; i++)
|
|
1413
1522
|
{
|
|
@@ -1591,12 +1700,65 @@ int DLLEXPORT EN_settimeparam(EN_Project p, int param, long value)
|
|
|
1591
1700
|
time->Qtime = value;
|
|
1592
1701
|
break;
|
|
1593
1702
|
|
|
1703
|
+
case EN_STARTTIME:
|
|
1704
|
+
if (value > SECperDAY) return 213;
|
|
1705
|
+
time->Tstart = value;
|
|
1706
|
+
break;
|
|
1707
|
+
|
|
1594
1708
|
default:
|
|
1595
1709
|
return 251;
|
|
1596
1710
|
}
|
|
1597
1711
|
return 0;
|
|
1598
1712
|
}
|
|
1599
1713
|
|
|
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
|
+
|
|
1600
1762
|
int DLLEXPORT EN_getqualinfo(EN_Project p, int *qualType, char *chemName,
|
|
1601
1763
|
char *chemUnits, int *traceNode)
|
|
1602
1764
|
/*----------------------------------------------------------------
|
|
@@ -1652,8 +1814,8 @@ int DLLEXPORT EN_getqualtype(EN_Project p, int *qualType, int *traceNode)
|
|
|
1652
1814
|
return 0;
|
|
1653
1815
|
}
|
|
1654
1816
|
|
|
1655
|
-
int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, char *chemName,
|
|
1656
|
-
char *chemUnits, char *traceNode)
|
|
1817
|
+
int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, const char *chemName,
|
|
1818
|
+
const char *chemUnits, const char *traceNode)
|
|
1657
1819
|
/*----------------------------------------------------------------
|
|
1658
1820
|
** Input: qualType = type of quality analysis to run (see EN_QualityType)
|
|
1659
1821
|
** chemname = name of chemical constituent
|
|
@@ -1670,7 +1832,7 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, char *chemName,
|
|
|
1670
1832
|
Quality *qual = &p->quality;
|
|
1671
1833
|
|
|
1672
1834
|
double *Ucf = p->Ucf;
|
|
1673
|
-
int i, oldQualFlag, traceNodeIndex;
|
|
1835
|
+
int i, oldQualFlag, traceNodeIndex = 0;
|
|
1674
1836
|
double ccf = 1.0;
|
|
1675
1837
|
|
|
1676
1838
|
if (!p->Openflag) return 102;
|
|
@@ -1682,6 +1844,7 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, char *chemName,
|
|
|
1682
1844
|
if (traceNodeIndex == 0) return 212;
|
|
1683
1845
|
}
|
|
1684
1846
|
|
|
1847
|
+
qual->TraceNode = traceNodeIndex;
|
|
1685
1848
|
oldQualFlag = qual->Qualflag;
|
|
1686
1849
|
qual->Qualflag = qualType;
|
|
1687
1850
|
qual->Ctol *= Ucf[QUALITY];
|
|
@@ -1696,8 +1859,6 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, char *chemName,
|
|
|
1696
1859
|
}
|
|
1697
1860
|
if (qual->Qualflag == TRACE) // Source trace analysis
|
|
1698
1861
|
{
|
|
1699
|
-
qual->TraceNode = findnode(net, traceNode);
|
|
1700
|
-
if (qual->TraceNode == 0) return 212;
|
|
1701
1862
|
strncpy(qual->ChemName, w_TRACE, MAXID);
|
|
1702
1863
|
strncpy(qual->ChemUnits, u_PERCENT, MAXID);
|
|
1703
1864
|
strcpy(rpt->Field[QUALITY].Units, u_PERCENT);
|
|
@@ -1732,7 +1893,7 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, char *chemName,
|
|
|
1732
1893
|
|
|
1733
1894
|
********************************************************************/
|
|
1734
1895
|
|
|
1735
|
-
int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType, int *index)
|
|
1896
|
+
int DLLEXPORT EN_addnode(EN_Project p, const char *id, int nodeType, int *index)
|
|
1736
1897
|
/*----------------------------------------------------------------
|
|
1737
1898
|
** Input: id = node ID name
|
|
1738
1899
|
** nodeType = type of node (see EN_NodeType)
|
|
@@ -1761,17 +1922,21 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType, int *index)
|
|
|
1761
1922
|
|
|
1762
1923
|
// Check if a node with same id already exists
|
|
1763
1924
|
if (EN_getnodeindex(p, id, &i) == 0) return 215;
|
|
1764
|
-
|
|
1925
|
+
|
|
1765
1926
|
// Check for valid node type
|
|
1766
|
-
if (nodeType < EN_JUNCTION || nodeType > EN_TANK) return 251;
|
|
1927
|
+
if (nodeType < EN_JUNCTION || nodeType > EN_TANK) return 251;
|
|
1767
1928
|
|
|
1768
|
-
// Grow node-related arrays to
|
|
1929
|
+
// Grow node-related arrays to accommodate the new node
|
|
1769
1930
|
size = (net->Nnodes + 2) * sizeof(Snode);
|
|
1770
1931
|
net->Node = (Snode *)realloc(net->Node, size);
|
|
1771
1932
|
size = (net->Nnodes + 2) * sizeof(double);
|
|
1772
1933
|
hyd->NodeDemand = (double *)realloc(hyd->NodeDemand, size);
|
|
1773
1934
|
qual->NodeQual = (double *)realloc(qual->NodeQual, size);
|
|
1774
1935
|
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);
|
|
1775
1940
|
|
|
1776
1941
|
// Actions taken when a new Junction is added
|
|
1777
1942
|
if (nodeType == EN_JUNCTION)
|
|
@@ -1782,7 +1947,7 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType, int *index)
|
|
|
1782
1947
|
hashtable_update(net->NodeHashTable, net->Node[i].ID, i + 1);
|
|
1783
1948
|
net->Node[i + 1] = net->Node[i];
|
|
1784
1949
|
}
|
|
1785
|
-
|
|
1950
|
+
|
|
1786
1951
|
// set index of new Junction node
|
|
1787
1952
|
net->Njuncs++;
|
|
1788
1953
|
nIdx = net->Njuncs;
|
|
@@ -1808,7 +1973,7 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType, int *index)
|
|
|
1808
1973
|
if (control->Node > net->Njuncs - 1) control->Node += 1;
|
|
1809
1974
|
}
|
|
1810
1975
|
// adjust indices of tanks/reservoirs in Rule premises (see RULES.C)
|
|
1811
|
-
adjusttankrules(p);
|
|
1976
|
+
adjusttankrules(p, 1);
|
|
1812
1977
|
}
|
|
1813
1978
|
|
|
1814
1979
|
// Actions taken when a new Tank/Reservoir is added
|
|
@@ -1840,7 +2005,7 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType, int *index)
|
|
|
1840
2005
|
tank->Pat = 0;
|
|
1841
2006
|
tank->Vcurve = 0;
|
|
1842
2007
|
tank->MixModel = 0;
|
|
1843
|
-
tank->
|
|
2008
|
+
tank->V1frac = 1;
|
|
1844
2009
|
tank->CanOverflow = FALSE;
|
|
1845
2010
|
}
|
|
1846
2011
|
net->Nnodes++;
|
|
@@ -1858,6 +2023,7 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType, int *index)
|
|
|
1858
2023
|
node->X = MISSING;
|
|
1859
2024
|
node->Y = MISSING;
|
|
1860
2025
|
node->Comment = NULL;
|
|
2026
|
+
node->Tag = NULL;
|
|
1861
2027
|
|
|
1862
2028
|
// Insert new node into hash table
|
|
1863
2029
|
hashtable_insert(net->NodeHashTable, node->ID, nIdx);
|
|
@@ -1917,6 +2083,7 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode)
|
|
|
1917
2083
|
freedemands(node);
|
|
1918
2084
|
free(node->S);
|
|
1919
2085
|
free(node->Comment);
|
|
2086
|
+
free(node->Tag);
|
|
1920
2087
|
|
|
1921
2088
|
// Shift position of higher entries in Node & Coord arrays down one
|
|
1922
2089
|
for (i = index; i <= net->Nnodes - 1; i++)
|
|
@@ -1925,6 +2092,7 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode)
|
|
|
1925
2092
|
// ... update node's entry in the hash table
|
|
1926
2093
|
hashtable_update(net->NodeHashTable, net->Node[i].ID, i);
|
|
1927
2094
|
}
|
|
2095
|
+
if (index < p->quality.TraceNode) (p->quality.TraceNode)--;
|
|
1928
2096
|
|
|
1929
2097
|
// If deleted node is a tank, remove it from the Tank array
|
|
1930
2098
|
if (nodeType != EN_JUNCTION)
|
|
@@ -1979,7 +2147,7 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode)
|
|
|
1979
2147
|
return 0;
|
|
1980
2148
|
}
|
|
1981
2149
|
|
|
1982
|
-
int DLLEXPORT EN_getnodeindex(EN_Project p, char *id, int *index)
|
|
2150
|
+
int DLLEXPORT EN_getnodeindex(EN_Project p, const char *id, int *index)
|
|
1983
2151
|
/*----------------------------------------------------------------
|
|
1984
2152
|
** Input: id = node ID name
|
|
1985
2153
|
** Output: index = node index
|
|
@@ -2011,7 +2179,7 @@ int DLLEXPORT EN_getnodeid(EN_Project p, int index, char *id)
|
|
|
2011
2179
|
return 0;
|
|
2012
2180
|
}
|
|
2013
2181
|
|
|
2014
|
-
int DLLEXPORT EN_setnodeid(EN_Project p, int index, char *newid)
|
|
2182
|
+
int DLLEXPORT EN_setnodeid(EN_Project p, int index, const char *newid)
|
|
2015
2183
|
/*----------------------------------------------------------------
|
|
2016
2184
|
** Input: index = node index
|
|
2017
2185
|
** newid = new node ID name
|
|
@@ -2074,8 +2242,10 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val
|
|
|
2074
2242
|
Network *net = &p->network;
|
|
2075
2243
|
Hydraul *hyd = &p->hydraul;
|
|
2076
2244
|
Quality *qual = &p->quality;
|
|
2245
|
+
Parser *parser = &p->parser;
|
|
2077
2246
|
|
|
2078
2247
|
double v = 0.0;
|
|
2248
|
+
double ecfTmp; // Unit conversion factor for emitter pressure
|
|
2079
2249
|
Psource source;
|
|
2080
2250
|
|
|
2081
2251
|
Snode *Node = net->Node;
|
|
@@ -2120,7 +2290,8 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val
|
|
|
2120
2290
|
v = 0.0;
|
|
2121
2291
|
if (Node[index].Ke > 0.0)
|
|
2122
2292
|
{
|
|
2123
|
-
|
|
2293
|
+
ecfTmp = (parser->Unitsflag == US) ? (PSIperFT * hyd->SpGrav) : MperFT;
|
|
2294
|
+
v = Ucf[FLOW] / pow((ecfTmp * Node[index].Ke), (1.0 / hyd->Qexp));
|
|
2124
2295
|
}
|
|
2125
2296
|
break;
|
|
2126
2297
|
|
|
@@ -2157,10 +2328,12 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val
|
|
|
2157
2328
|
|
|
2158
2329
|
case EN_MIXZONEVOL:
|
|
2159
2330
|
v = 0.0;
|
|
2160
|
-
if (index > nJuncs)
|
|
2331
|
+
if (index > nJuncs)
|
|
2332
|
+
v = Tank[index - nJuncs].V1frac * Tank[index - nJuncs].Vmax *
|
|
2333
|
+
Ucf[VOLUME];
|
|
2161
2334
|
break;
|
|
2162
2335
|
|
|
2163
|
-
case EN_DEMAND:
|
|
2336
|
+
case EN_DEMAND: // Consumer Demand + Emitter Flow + Leakage Flow
|
|
2164
2337
|
v = hyd->NodeDemand[index] * Ucf[FLOW];
|
|
2165
2338
|
break;
|
|
2166
2339
|
|
|
@@ -2217,9 +2390,9 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val
|
|
|
2217
2390
|
|
|
2218
2391
|
case EN_MIXFRACTION:
|
|
2219
2392
|
v = 1.0;
|
|
2220
|
-
if (index > nJuncs
|
|
2393
|
+
if (index > nJuncs)
|
|
2221
2394
|
{
|
|
2222
|
-
v = Tank[index - nJuncs].
|
|
2395
|
+
v = Tank[index - nJuncs].V1frac;
|
|
2223
2396
|
}
|
|
2224
2397
|
break;
|
|
2225
2398
|
|
|
@@ -2237,14 +2410,34 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val
|
|
|
2237
2410
|
if (Node[index].Type != TANK) return 0;
|
|
2238
2411
|
v = Tank[index - nJuncs].CanOverflow;
|
|
2239
2412
|
break;
|
|
2240
|
-
|
|
2413
|
+
|
|
2241
2414
|
case EN_DEMANDDEFICIT:
|
|
2242
2415
|
if (index > nJuncs) return 0;
|
|
2243
|
-
//
|
|
2244
|
-
// while
|
|
2245
|
-
if (hyd->
|
|
2246
|
-
v = (hyd->
|
|
2247
|
-
|
|
2416
|
+
// FullDemand contains node's required consumer demand
|
|
2417
|
+
// while DemandFlow contains delivered consumer demand
|
|
2418
|
+
if (hyd->FullDemand[index] <= 0.0) return 0;
|
|
2419
|
+
v = (hyd->FullDemand[index] - hyd->DemandFlow[index]) * Ucf[FLOW];
|
|
2420
|
+
if (v < 0.0) v = 0.0;
|
|
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];
|
|
2248
2441
|
break;
|
|
2249
2442
|
|
|
2250
2443
|
default:
|
|
@@ -2254,6 +2447,25 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val
|
|
|
2254
2447
|
return 0;
|
|
2255
2448
|
}
|
|
2256
2449
|
|
|
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
|
+
|
|
2257
2469
|
int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double value)
|
|
2258
2470
|
/*----------------------------------------------------------------
|
|
2259
2471
|
** Input: index = node index
|
|
@@ -2268,6 +2480,7 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2268
2480
|
Network *net = &p->network;
|
|
2269
2481
|
Hydraul *hyd = &p->hydraul;
|
|
2270
2482
|
Quality *qual = &p->quality;
|
|
2483
|
+
Parser *parser = &p->parser;
|
|
2271
2484
|
|
|
2272
2485
|
Snode *Node = net->Node;
|
|
2273
2486
|
Stank *Tank = net->Tank;
|
|
@@ -2281,8 +2494,7 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2281
2494
|
|
|
2282
2495
|
int i, j, n;
|
|
2283
2496
|
Psource source;
|
|
2284
|
-
double hTmp;
|
|
2285
|
-
double vTmp;
|
|
2497
|
+
double hTmp, ecfTmp;
|
|
2286
2498
|
|
|
2287
2499
|
if (!p->Openflag) return 102;
|
|
2288
2500
|
if (index <= 0 || index > nNodes) return 203;
|
|
@@ -2324,8 +2536,13 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2324
2536
|
case EN_EMITTER:
|
|
2325
2537
|
if (index > nJuncs) return 0;
|
|
2326
2538
|
if (value < 0.0) return 209;
|
|
2327
|
-
if (value > 0.0)
|
|
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
|
+
}
|
|
2328
2544
|
Node[index].Ke = value;
|
|
2545
|
+
if (hyd->EmitterFlow[index] == 0.0) hyd->EmitterFlow[index] = 1.0;
|
|
2329
2546
|
break;
|
|
2330
2547
|
|
|
2331
2548
|
case EN_INITQUAL:
|
|
@@ -2364,7 +2581,7 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2364
2581
|
break;
|
|
2365
2582
|
|
|
2366
2583
|
case EN_TANKLEVEL:
|
|
2367
|
-
if (index <= nJuncs) return
|
|
2584
|
+
if (index <= nJuncs) return 263;
|
|
2368
2585
|
j = index - nJuncs;
|
|
2369
2586
|
if (Tank[j].A == 0.0) /* Tank is a reservoir */
|
|
2370
2587
|
{
|
|
@@ -2388,9 +2605,9 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2388
2605
|
|
|
2389
2606
|
case EN_TANKDIAM:
|
|
2390
2607
|
if (value <= 0.0) return 209; // invalid diameter
|
|
2391
|
-
if (index <= nJuncs) return
|
|
2608
|
+
if (index <= nJuncs) return 263; // node is not a tank
|
|
2392
2609
|
j = index - nJuncs; // tank index
|
|
2393
|
-
if (Tank[j].A == 0.0) return
|
|
2610
|
+
if (Tank[j].A == 0.0) return 263; // tank is a reservoir
|
|
2394
2611
|
value /= Ucf[ELEV]; // diameter in feet
|
|
2395
2612
|
Tank[j].A = PI * SQR(value) / 4.0; // new tank area
|
|
2396
2613
|
if (Tank[j].Vcurve > 0) // tank has a volume curve
|
|
@@ -2399,7 +2616,7 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2399
2616
|
|
|
2400
2617
|
// Since the volume curve no longer applies we assume that the tank's
|
|
2401
2618
|
// shape below Hmin is cylindrical and Vmin equals area times Hmin
|
|
2402
|
-
Tank[j].Vmin = Tank[j].A * Tank[j].Hmin;
|
|
2619
|
+
Tank[j].Vmin = Tank[j].A * (Tank[j].Hmin - Node[index].El);
|
|
2403
2620
|
}
|
|
2404
2621
|
// Since tank's area has changed its volumes must be updated
|
|
2405
2622
|
// NOTE: For a non-volume curve tank we can't change the Vmin
|
|
@@ -2407,16 +2624,14 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2407
2624
|
// shape below Hmin. Vmin can always be changed by setting
|
|
2408
2625
|
// EN_MINVOLUME in a subsequent function call.
|
|
2409
2626
|
Tank[j].V0 = tankvolume(p, j, Tank[j].H0); // new init. volume
|
|
2410
|
-
vTmp = Tank[j].Vmax; // old max. volume
|
|
2411
2627
|
Tank[j].Vmax = tankvolume(p, j, Tank[j].Hmax); // new max. volume
|
|
2412
|
-
Tank[j].V1max *= Tank[j].Vmax / vTmp; // new mix zone volume
|
|
2413
2628
|
break;
|
|
2414
2629
|
|
|
2415
2630
|
case EN_MINVOLUME:
|
|
2416
2631
|
if (value < 0.0) return 209; // invalid volume
|
|
2417
|
-
if (index <= nJuncs) return
|
|
2632
|
+
if (index <= nJuncs) return 263; // node is not a tank
|
|
2418
2633
|
j = index - nJuncs; // tank index
|
|
2419
|
-
if (Tank[j].A == 0.0) return
|
|
2634
|
+
if (Tank[j].A == 0.0) return 263; // tank is a reservoir
|
|
2420
2635
|
i = Tank[j].Vcurve; // volume curve index
|
|
2421
2636
|
if (i > 0) // tank has a volume curve
|
|
2422
2637
|
{
|
|
@@ -2434,14 +2649,12 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2434
2649
|
// If the volume supplied by the function is 0 then the tank shape
|
|
2435
2650
|
// below Hmin is assumed to be cylindrical and a new Vmin value is
|
|
2436
2651
|
// computed. Otherwise Vmin is set to the supplied value.
|
|
2437
|
-
if (value == 0.0) Tank[j].Vmin = Tank[j].A * Tank[j].Hmin;
|
|
2652
|
+
if (value == 0.0) Tank[j].Vmin = Tank[j].A * (Tank[j].Hmin - Node[index].El);
|
|
2438
2653
|
else Tank[j].Vmin = value / Ucf[VOLUME];
|
|
2439
2654
|
|
|
2440
2655
|
// Since Vmin changes the other volumes need updating
|
|
2441
2656
|
Tank[j].V0 = tankvolume(p, j, Tank[j].H0); // new init. volume
|
|
2442
|
-
vTmp = Tank[j].Vmax; // old max. volume
|
|
2443
2657
|
Tank[j].Vmax = tankvolume(p, j, Tank[j].Hmax); // new max. volume
|
|
2444
|
-
Tank[j].V1max *= Tank[j].Vmax / vTmp; // new mix zone volume
|
|
2445
2658
|
}
|
|
2446
2659
|
break;
|
|
2447
2660
|
|
|
@@ -2451,9 +2664,9 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2451
2664
|
i = ROUND(value); // curve index
|
|
2452
2665
|
if (i <= 0 ||
|
|
2453
2666
|
i > net->Ncurves) return 205; // invalid curve index
|
|
2454
|
-
if (index <= nJuncs) return
|
|
2667
|
+
if (index <= nJuncs) return 263; // node not a tank
|
|
2455
2668
|
j = index - nJuncs; // tank index
|
|
2456
|
-
if (Tank[j].A == 0.0) return
|
|
2669
|
+
if (Tank[j].A == 0.0) return 263; // tank is a reservoir
|
|
2457
2670
|
curve = &net->Curve[i]; // curve object
|
|
2458
2671
|
|
|
2459
2672
|
// Check that tank's min/max levels lie within curve
|
|
@@ -2466,18 +2679,16 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2466
2679
|
Tank[j].Vcurve = i; // assign curve to tank
|
|
2467
2680
|
Tank[j].Vmin = tankvolume(p, j, Tank[j].Hmin); // new min. volume
|
|
2468
2681
|
Tank[j].V0 = tankvolume(p, j, Tank[j].H0); // new init. volume
|
|
2469
|
-
vTmp = Tank[j].Vmax; // old max. volume
|
|
2470
2682
|
Tank[j].Vmax = tankvolume(p, j, Tank[j].Hmax); // new max. volume
|
|
2471
|
-
Tank[j].
|
|
2472
|
-
Tank[j].A = (curve->Y[n] - curve->Y[0]) / // nominal area
|
|
2683
|
+
Tank[j].A = (curve->Y[n] - curve->Y[0]) / // nominal area
|
|
2473
2684
|
(curve->X[n] - curve->X[0]);
|
|
2474
2685
|
break;
|
|
2475
2686
|
|
|
2476
2687
|
case EN_MINLEVEL:
|
|
2477
2688
|
if (value < 0.0) return 209; // invalid water level
|
|
2478
|
-
if (index <= nJuncs) return
|
|
2689
|
+
if (index <= nJuncs) return 263; // node not a tank
|
|
2479
2690
|
j = index - nJuncs; // tank index
|
|
2480
|
-
if (Tank[j].A == 0.0) return
|
|
2691
|
+
if (Tank[j].A == 0.0) return 263; // tank is a reservoir
|
|
2481
2692
|
hTmp = value / Ucf[ELEV] + Node[index].El; // convert level to head
|
|
2482
2693
|
if (hTmp >= Tank[j].Hmax ||
|
|
2483
2694
|
hTmp > Tank[j].H0) return 225; // invalid water levels
|
|
@@ -2496,9 +2707,9 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2496
2707
|
|
|
2497
2708
|
case EN_MAXLEVEL:
|
|
2498
2709
|
if (value <= 0.0) return 209; // invalid water level
|
|
2499
|
-
if (index <= nJuncs) return
|
|
2710
|
+
if (index <= nJuncs) return 263; // node not a tank
|
|
2500
2711
|
j = index - nJuncs; // tank index
|
|
2501
|
-
if (Tank[j].A == 0.0) return
|
|
2712
|
+
if (Tank[j].A == 0.0) return 263; // tank is a reservoir
|
|
2502
2713
|
hTmp = value / Ucf[ELEV] + Node[index].El; // convert level to head
|
|
2503
2714
|
if (hTmp < Tank[j].Hmin ||
|
|
2504
2715
|
hTmp < Tank[j].H0) return 225; // invalid water levels
|
|
@@ -2510,14 +2721,12 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2510
2721
|
if (value > curve->X[n]) return 225; // new level is off curve
|
|
2511
2722
|
}
|
|
2512
2723
|
Tank[j].Hmax = hTmp; // new max. head
|
|
2513
|
-
vTmp = Tank[j].Vmax; // old max. volume
|
|
2514
2724
|
Tank[j].Vmax = tankvolume(p, j, hTmp); // new max. volume
|
|
2515
|
-
Tank[j].V1max *= Tank[j].Vmax / vTmp; // new mix zone volume
|
|
2516
2725
|
break;
|
|
2517
2726
|
|
|
2518
2727
|
case EN_MIXMODEL:
|
|
2519
2728
|
j = ROUND(value);
|
|
2520
|
-
if (index <= nJuncs) return
|
|
2729
|
+
if (index <= nJuncs) return 263;
|
|
2521
2730
|
if (j < MIX1 || j > LIFO) return 251;
|
|
2522
2731
|
if (Tank[index - nJuncs].A > 0.0)
|
|
2523
2732
|
{
|
|
@@ -2526,17 +2735,17 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2526
2735
|
break;
|
|
2527
2736
|
|
|
2528
2737
|
case EN_MIXFRACTION:
|
|
2529
|
-
if (index <= nJuncs) return
|
|
2738
|
+
if (index <= nJuncs) return 263;
|
|
2530
2739
|
if (value < 0.0 || value > 1.0) return 209;
|
|
2531
2740
|
j = index - nJuncs;
|
|
2532
2741
|
if (Tank[j].A > 0.0)
|
|
2533
2742
|
{
|
|
2534
|
-
Tank[j].
|
|
2743
|
+
Tank[j].V1frac = value;
|
|
2535
2744
|
}
|
|
2536
2745
|
break;
|
|
2537
2746
|
|
|
2538
2747
|
case EN_TANK_KBULK:
|
|
2539
|
-
if (index <= nJuncs) return
|
|
2748
|
+
if (index <= nJuncs) return 263;
|
|
2540
2749
|
j = index - nJuncs;
|
|
2541
2750
|
if (Tank[j].A > 0.0)
|
|
2542
2751
|
{
|
|
@@ -2546,7 +2755,7 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2546
2755
|
break;
|
|
2547
2756
|
|
|
2548
2757
|
case EN_CANOVERFLOW:
|
|
2549
|
-
if (Node[index].Type != TANK) return
|
|
2758
|
+
if (Node[index].Type != TANK) return 263;
|
|
2550
2759
|
Tank[index - nJuncs].CanOverflow = (value != 0.0);
|
|
2551
2760
|
break;
|
|
2552
2761
|
|
|
@@ -2557,7 +2766,7 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|
|
2557
2766
|
}
|
|
2558
2767
|
|
|
2559
2768
|
int DLLEXPORT EN_setjuncdata(EN_Project p, int index, double elev,
|
|
2560
|
-
double dmnd, char *dmndpat)
|
|
2769
|
+
double dmnd, const char *dmndpat)
|
|
2561
2770
|
/*----------------------------------------------------------------
|
|
2562
2771
|
** Input: index = junction node index
|
|
2563
2772
|
** elev = junction elevation
|
|
@@ -2602,7 +2811,7 @@ int DLLEXPORT EN_setjuncdata(EN_Project p, int index, double elev,
|
|
|
2602
2811
|
int DLLEXPORT EN_settankdata(EN_Project p, int index, double elev,
|
|
2603
2812
|
double initlvl, double minlvl,
|
|
2604
2813
|
double maxlvl, double diam,
|
|
2605
|
-
double minvol, char *volcurve)
|
|
2814
|
+
double minvol, const char *volcurve)
|
|
2606
2815
|
/*----------------------------------------------------------------
|
|
2607
2816
|
** Input: index = tank node index
|
|
2608
2817
|
** elev = tank bottom elevation
|
|
@@ -2621,16 +2830,16 @@ int DLLEXPORT EN_settankdata(EN_Project p, int index, double elev,
|
|
|
2621
2830
|
Network *net = &p->network;
|
|
2622
2831
|
|
|
2623
2832
|
int i, j, n, curveIndex = 0;
|
|
2624
|
-
double area, elevation = elev;
|
|
2625
2833
|
double *Ucf = p->Ucf;
|
|
2834
|
+
double area;
|
|
2626
2835
|
Stank *Tank = net->Tank;
|
|
2627
2836
|
Scurve *curve;
|
|
2628
2837
|
|
|
2629
2838
|
// Check that tank exists
|
|
2630
2839
|
if (!p->Openflag) return 102;
|
|
2631
|
-
if (index <= net->Njuncs || index > net->Nnodes) return
|
|
2840
|
+
if (index <= net->Njuncs || index > net->Nnodes) return 263;
|
|
2632
2841
|
j = index - net->Njuncs;
|
|
2633
|
-
if (Tank[j].A == 0) return
|
|
2842
|
+
if (Tank[j].A == 0) return 263; // Tank is a Reservoir
|
|
2634
2843
|
|
|
2635
2844
|
// Check for valid parameter values
|
|
2636
2845
|
if (initlvl < 0.0 || minlvl < 0.0 || maxlvl < 0.0) return 209;
|
|
@@ -2659,16 +2868,16 @@ int DLLEXPORT EN_settankdata(EN_Project p, int index, double elev,
|
|
|
2659
2868
|
else area = PI * diam * diam / 4.0;
|
|
2660
2869
|
|
|
2661
2870
|
// Assign parameters to tank object
|
|
2662
|
-
net->Node[Tank[j].Node].El =
|
|
2871
|
+
net->Node[Tank[j].Node].El = elev / Ucf[ELEV];
|
|
2663
2872
|
Tank[j].A = area / Ucf[ELEV] / Ucf[ELEV];
|
|
2664
|
-
Tank[j].H0 =
|
|
2665
|
-
Tank[j].Hmin =
|
|
2666
|
-
Tank[j].Hmax =
|
|
2873
|
+
Tank[j].H0 = (elev + initlvl) / Ucf[ELEV];
|
|
2874
|
+
Tank[j].Hmin = (elev + minlvl) / Ucf[ELEV];
|
|
2875
|
+
Tank[j].Hmax = (elev + maxlvl) / Ucf[ELEV];
|
|
2667
2876
|
Tank[j].Vcurve = curveIndex;
|
|
2668
2877
|
if (curveIndex == 0)
|
|
2669
2878
|
{
|
|
2670
2879
|
if (minvol > 0.0) Tank[j].Vmin = minvol / Ucf[VOLUME];
|
|
2671
|
-
else Tank[j].Vmin = Tank[j].A * Tank[j].Hmin;
|
|
2880
|
+
else Tank[j].Vmin = Tank[j].A * (Tank[j].Hmin - elev / Ucf[ELEV]);
|
|
2672
2881
|
}
|
|
2673
2882
|
else Tank[j].Vmin = tankvolume(p, j, Tank[j].Hmin);
|
|
2674
2883
|
Tank[j].V0 = tankvolume(p, j, Tank[j].H0);
|
|
@@ -2778,7 +2987,7 @@ int DLLEXPORT EN_setdemandmodel(EN_Project p, int model, double pmin,
|
|
|
2778
2987
|
}
|
|
2779
2988
|
|
|
2780
2989
|
int DLLEXPORT EN_adddemand(EN_Project p, int nodeIndex, double baseDemand,
|
|
2781
|
-
char *demandPattern, char *demandName)
|
|
2990
|
+
const char *demandPattern, const char *demandName)
|
|
2782
2991
|
/*----------------------------------------------------------------
|
|
2783
2992
|
** Input: nodeIndex = node index
|
|
2784
2993
|
** baseDemand = baseline demand value
|
|
@@ -2865,7 +3074,7 @@ int DLLEXPORT EN_deletedemand(EN_Project p, int nodeIndex, int demandIndex)
|
|
|
2865
3074
|
return 0;
|
|
2866
3075
|
}
|
|
2867
3076
|
|
|
2868
|
-
int DLLEXPORT EN_getdemandindex(EN_Project p, int nodeIndex, char *demandName,
|
|
3077
|
+
int DLLEXPORT EN_getdemandindex(EN_Project p, int nodeIndex, const char *demandName,
|
|
2869
3078
|
int *demandIndex)
|
|
2870
3079
|
/*----------------------------------------------------------------
|
|
2871
3080
|
** Input: nodeIndex = node index
|
|
@@ -3014,7 +3223,7 @@ int DLLEXPORT EN_getdemandname(EN_Project p, int nodeIndex, int demandIndex,
|
|
|
3014
3223
|
}
|
|
3015
3224
|
|
|
3016
3225
|
int DLLEXPORT EN_setdemandname(EN_Project p, int nodeIndex, int demandIndex,
|
|
3017
|
-
char *demandName)
|
|
3226
|
+
const char *demandName)
|
|
3018
3227
|
/*----------------------------------------------------------------
|
|
3019
3228
|
** Input: nodeIndex = node index
|
|
3020
3229
|
** demandIndex = demand category index
|
|
@@ -3104,8 +3313,8 @@ int DLLEXPORT EN_setdemandpattern(EN_Project p, int nodeIndex, int demandIndex,
|
|
|
3104
3313
|
|
|
3105
3314
|
********************************************************************/
|
|
3106
3315
|
|
|
3107
|
-
int DLLEXPORT EN_addlink(EN_Project p, char *id, int linkType,
|
|
3108
|
-
char *fromNode, char *toNode, int *index)
|
|
3316
|
+
int DLLEXPORT EN_addlink(EN_Project p, const char *id, int linkType,
|
|
3317
|
+
const char *fromNode, const char *toNode, int *index)
|
|
3109
3318
|
/*----------------------------------------------------------------
|
|
3110
3319
|
** Input: id = link ID name
|
|
3111
3320
|
** type = link type (see EN_LinkType)
|
|
@@ -3137,7 +3346,7 @@ int DLLEXPORT EN_addlink(EN_Project p, char *id, int linkType,
|
|
|
3137
3346
|
if (EN_getlinkindex(p, id, &i) == 0) return 215;
|
|
3138
3347
|
|
|
3139
3348
|
// Check for valid link type
|
|
3140
|
-
if (linkType < CVPIPE || linkType >
|
|
3349
|
+
if (linkType < CVPIPE || linkType > PCV) return 251;
|
|
3141
3350
|
|
|
3142
3351
|
// Lookup the link's from and to nodes
|
|
3143
3352
|
n1 = hashtable_find(net->NodeHashTable, fromNode);
|
|
@@ -3151,7 +3360,7 @@ int DLLEXPORT EN_addlink(EN_Project p, char *id, int linkType,
|
|
|
3151
3360
|
if (errcode) return errcode;
|
|
3152
3361
|
}
|
|
3153
3362
|
|
|
3154
|
-
// Grow link-related arrays to
|
|
3363
|
+
// Grow link-related arrays to accommodate the new link
|
|
3155
3364
|
net->Nlinks++;
|
|
3156
3365
|
p->parser.MaxLinks = net->Nlinks;
|
|
3157
3366
|
n = net->Nlinks;
|
|
@@ -3170,7 +3379,7 @@ int DLLEXPORT EN_addlink(EN_Project p, char *id, int linkType,
|
|
|
3170
3379
|
if (linkType <= PIPE) net->Npipes++;
|
|
3171
3380
|
else if (linkType == PUMP)
|
|
3172
3381
|
{
|
|
3173
|
-
// Grow pump array to
|
|
3382
|
+
// Grow pump array to accommodate the new link
|
|
3174
3383
|
net->Npumps++;
|
|
3175
3384
|
size = (net->Npumps + 1) * sizeof(Spump);
|
|
3176
3385
|
net->Pump = (Spump *)realloc(net->Pump, size);
|
|
@@ -3192,17 +3401,18 @@ int DLLEXPORT EN_addlink(EN_Project p, char *id, int linkType,
|
|
|
3192
3401
|
}
|
|
3193
3402
|
else
|
|
3194
3403
|
{
|
|
3195
|
-
// Grow valve array to
|
|
3404
|
+
// Grow valve array to accommodate the new link
|
|
3196
3405
|
net->Nvalves++;
|
|
3197
3406
|
size = (net->Nvalves + 1) * sizeof(Svalve);
|
|
3198
3407
|
net->Valve = (Svalve *)realloc(net->Valve, size);
|
|
3199
3408
|
net->Valve[net->Nvalves].Link = n;
|
|
3409
|
+
net->Valve[net->Nvalves].Curve = 0;
|
|
3200
3410
|
}
|
|
3201
3411
|
|
|
3202
3412
|
link->Type = linkType;
|
|
3203
3413
|
link->N1 = n1;
|
|
3204
3414
|
link->N2 = n2;
|
|
3205
|
-
link->
|
|
3415
|
+
link->InitStatus = OPEN;
|
|
3206
3416
|
|
|
3207
3417
|
if (linkType == PUMP)
|
|
3208
3418
|
{
|
|
@@ -3231,15 +3441,19 @@ int DLLEXPORT EN_addlink(EN_Project p, char *id, int linkType,
|
|
|
3231
3441
|
link->Kc = 0.0; // Valve setting.
|
|
3232
3442
|
link->Km = 0.0; // Loss coeff
|
|
3233
3443
|
link->Len = 0.0;
|
|
3234
|
-
link->
|
|
3444
|
+
link->InitStatus = ACTIVE;
|
|
3235
3445
|
}
|
|
3236
3446
|
link->Kb = 0;
|
|
3237
3447
|
link->Kw = 0;
|
|
3448
|
+
link->LeakArea = 0;
|
|
3449
|
+
link->LeakExpan = 0;
|
|
3450
|
+
link->InitSetting = link->Kc;
|
|
3238
3451
|
link->R = 0;
|
|
3239
3452
|
link->Rc = 0;
|
|
3240
3453
|
link->Rpt = 0;
|
|
3241
3454
|
link->ResultIndex = 0;
|
|
3242
3455
|
link->Comment = NULL;
|
|
3456
|
+
link->Tag = NULL;
|
|
3243
3457
|
link->Vertices = NULL;
|
|
3244
3458
|
|
|
3245
3459
|
hashtable_insert(net->LinkHashTable, link->ID, n);
|
|
@@ -3292,6 +3506,7 @@ int DLLEXPORT EN_deletelink(EN_Project p, int index, int actionCode)
|
|
|
3292
3506
|
|
|
3293
3507
|
// Remove link's comment and vertices
|
|
3294
3508
|
free(link->Comment);
|
|
3509
|
+
free(link->Tag);
|
|
3295
3510
|
freelinkvertices(link);
|
|
3296
3511
|
|
|
3297
3512
|
// Shift position of higher entries in Link array down one
|
|
@@ -3312,6 +3527,12 @@ int DLLEXPORT EN_deletelink(EN_Project p, int index, int actionCode)
|
|
|
3312
3527
|
if (net->Valve[i].Link > index) net->Valve[i].Link -= 1;
|
|
3313
3528
|
}
|
|
3314
3529
|
|
|
3530
|
+
// Reduce the number of pipes count by one if it is a pipe.
|
|
3531
|
+
if (linkType == PIPE)
|
|
3532
|
+
{
|
|
3533
|
+
net->Npipes--;
|
|
3534
|
+
}
|
|
3535
|
+
|
|
3315
3536
|
// Delete any pump associated with the deleted link
|
|
3316
3537
|
if (linkType == PUMP)
|
|
3317
3538
|
{
|
|
@@ -3354,7 +3575,7 @@ int DLLEXPORT EN_deletelink(EN_Project p, int index, int actionCode)
|
|
|
3354
3575
|
return 0;
|
|
3355
3576
|
}
|
|
3356
3577
|
|
|
3357
|
-
int DLLEXPORT EN_getlinkindex(EN_Project p, char *id, int *index)
|
|
3578
|
+
int DLLEXPORT EN_getlinkindex(EN_Project p, const char *id, int *index)
|
|
3358
3579
|
/*----------------------------------------------------------------
|
|
3359
3580
|
** Input: id = link ID name
|
|
3360
3581
|
** Output: index = link index
|
|
@@ -3386,7 +3607,7 @@ int DLLEXPORT EN_getlinkid(EN_Project p, int index, char *id)
|
|
|
3386
3607
|
return 0;
|
|
3387
3608
|
}
|
|
3388
3609
|
|
|
3389
|
-
int DLLEXPORT EN_setlinkid(EN_Project p, int index, char *newid)
|
|
3610
|
+
int DLLEXPORT EN_setlinkid(EN_Project p, int index, const char *newid)
|
|
3390
3611
|
/*----------------------------------------------------------------
|
|
3391
3612
|
** Input: index = link index
|
|
3392
3613
|
** id = link ID name
|
|
@@ -3456,7 +3677,7 @@ int DLLEXPORT EN_setlinktype(EN_Project p, int *index, int linkType, int actionC
|
|
|
3456
3677
|
if (p->hydraul.OpenHflag || p->quality.OpenQflag) return 262;
|
|
3457
3678
|
|
|
3458
3679
|
// Check for valid input parameters
|
|
3459
|
-
if (linkType < 0 || linkType >
|
|
3680
|
+
if (linkType < 0 || linkType > PCV || actionCode < EN_UNCONDITIONAL ||
|
|
3460
3681
|
actionCode > EN_CONDITIONAL)
|
|
3461
3682
|
{
|
|
3462
3683
|
return 251;
|
|
@@ -3480,7 +3701,7 @@ int DLLEXPORT EN_setlinktype(EN_Project p, int *index, int linkType, int actionC
|
|
|
3480
3701
|
if (oldType <= PIPE && linkType <= PIPE)
|
|
3481
3702
|
{
|
|
3482
3703
|
net->Link[i].Type = linkType;
|
|
3483
|
-
if (linkType == CVPIPE) net->Link[i].
|
|
3704
|
+
if (linkType == CVPIPE) net->Link[i].InitStatus = OPEN;
|
|
3484
3705
|
return 0;
|
|
3485
3706
|
}
|
|
3486
3707
|
|
|
@@ -3583,8 +3804,6 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val
|
|
|
3583
3804
|
Slink *Link = net->Link;
|
|
3584
3805
|
Spump *Pump = net->Pump;
|
|
3585
3806
|
double *Ucf = p->Ucf;
|
|
3586
|
-
double *LinkFlow = hyd->LinkFlow;
|
|
3587
|
-
double *LinkSetting = hyd->LinkSetting;
|
|
3588
3807
|
|
|
3589
3808
|
// Check for valid arguments
|
|
3590
3809
|
*value = 0.0;
|
|
@@ -3622,18 +3841,19 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val
|
|
|
3622
3841
|
break;
|
|
3623
3842
|
|
|
3624
3843
|
case EN_INITSTATUS:
|
|
3625
|
-
if (Link[index].
|
|
3844
|
+
if (Link[index].InitStatus <= CLOSED) v = 0.0;
|
|
3626
3845
|
else v = 1.0;
|
|
3846
|
+
if (Link[index].Type > PUMP && Link[index].InitStatus > OPEN) v = 2.0;
|
|
3627
3847
|
break;
|
|
3628
3848
|
|
|
3629
3849
|
case EN_INITSETTING:
|
|
3630
|
-
|
|
3631
|
-
{
|
|
3632
|
-
return EN_getlinkvalue(p, index, EN_ROUGHNESS, value);
|
|
3633
|
-
}
|
|
3634
|
-
v = Link[index].Kc;
|
|
3850
|
+
v = Link[index].InitSetting;
|
|
3635
3851
|
switch (Link[index].Type)
|
|
3636
3852
|
{
|
|
3853
|
+
case CVPIPE:
|
|
3854
|
+
case PIPE:
|
|
3855
|
+
if (hyd->Formflag == DW) v = v * (1000.0 * Ucf[ELEV]);
|
|
3856
|
+
break;
|
|
3637
3857
|
case PRV:
|
|
3638
3858
|
case PSV:
|
|
3639
3859
|
case PBV:
|
|
@@ -3656,7 +3876,7 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val
|
|
|
3656
3876
|
|
|
3657
3877
|
case EN_FLOW:
|
|
3658
3878
|
if (hyd->LinkStatus[index] <= CLOSED) v = 0.0;
|
|
3659
|
-
else v = LinkFlow[index] * Ucf[FLOW];
|
|
3879
|
+
else v = hyd->LinkFlow[index] * Ucf[FLOW];
|
|
3660
3880
|
break;
|
|
3661
3881
|
|
|
3662
3882
|
case EN_VELOCITY:
|
|
@@ -3664,7 +3884,7 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val
|
|
|
3664
3884
|
else if (hyd->LinkStatus[index] <= CLOSED) v = 0.0;
|
|
3665
3885
|
else
|
|
3666
3886
|
{
|
|
3667
|
-
q = ABS(LinkFlow[index]);
|
|
3887
|
+
q = ABS(hyd->LinkFlow[index]);
|
|
3668
3888
|
a = PI * SQR(Link[index].Diam) / 4.0;
|
|
3669
3889
|
v = q / a * Ucf[VELOCITY];
|
|
3670
3890
|
}
|
|
@@ -3683,6 +3903,8 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val
|
|
|
3683
3903
|
case EN_STATUS:
|
|
3684
3904
|
if (hyd->LinkStatus[index] <= CLOSED) v = 0.0;
|
|
3685
3905
|
else v = 1.0;
|
|
3906
|
+
if (Link[index].Type > PUMP &&
|
|
3907
|
+
hyd->LinkStatus[index] > OPEN) v = 2.0;
|
|
3686
3908
|
break;
|
|
3687
3909
|
|
|
3688
3910
|
case EN_SETTING:
|
|
@@ -3690,8 +3912,8 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val
|
|
|
3690
3912
|
{
|
|
3691
3913
|
return EN_getlinkvalue(p, index, EN_ROUGHNESS, value);
|
|
3692
3914
|
}
|
|
3693
|
-
if (LinkSetting[index] == MISSING) v = 0.0;
|
|
3694
|
-
else v = LinkSetting[index];
|
|
3915
|
+
if (hyd->LinkSetting[index] == MISSING) v = 0.0;
|
|
3916
|
+
else v = hyd->LinkSetting[index];
|
|
3695
3917
|
switch (Link[index].Type)
|
|
3696
3918
|
{
|
|
3697
3919
|
case PRV:
|
|
@@ -3778,6 +4000,40 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val
|
|
|
3778
4000
|
v = (double)Pump[findpump(&p->network, index)].Epat;
|
|
3779
4001
|
}
|
|
3780
4002
|
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;
|
|
3781
4037
|
|
|
3782
4038
|
default:
|
|
3783
4039
|
return 251;
|
|
@@ -3786,6 +4042,24 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val
|
|
|
3786
4042
|
return 0;
|
|
3787
4043
|
}
|
|
3788
4044
|
|
|
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
|
+
|
|
3789
4063
|
int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double value)
|
|
3790
4064
|
/*----------------------------------------------------------------
|
|
3791
4065
|
** Input: index = link index
|
|
@@ -3803,10 +4077,9 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu
|
|
|
3803
4077
|
|
|
3804
4078
|
Slink *Link = net->Link;
|
|
3805
4079
|
double *Ucf = p->Ucf;
|
|
3806
|
-
double *LinkSetting = hyd->LinkSetting;
|
|
3807
4080
|
char s;
|
|
3808
4081
|
double r;
|
|
3809
|
-
int pumpIndex, patIndex, curveIndex;
|
|
4082
|
+
int pumpIndex, patIndex, curveIndex, valveType;
|
|
3810
4083
|
|
|
3811
4084
|
if (!p->Openflag) return 102;
|
|
3812
4085
|
if (index <= 0 || index > net->Nlinks) return 204;
|
|
@@ -3839,14 +4112,15 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu
|
|
|
3839
4112
|
if (value <= 0.0) return 211;
|
|
3840
4113
|
Link[index].Kc = value;
|
|
3841
4114
|
if (hyd->Formflag == DW) Link[index].Kc /= (1000.0 * Ucf[ELEV]);
|
|
3842
|
-
resistcoeff(p, index);
|
|
4115
|
+
if (p->hydraul.OpenHflag) resistcoeff(p, index);
|
|
4116
|
+
else Link[index].InitSetting = Link[index].Kc;
|
|
3843
4117
|
}
|
|
3844
4118
|
break;
|
|
3845
4119
|
|
|
3846
4120
|
case EN_MINORLOSS:
|
|
3847
4121
|
if (Link[index].Type != PUMP)
|
|
3848
4122
|
{
|
|
3849
|
-
if (value
|
|
4123
|
+
if (value < 0.0) return 211;
|
|
3850
4124
|
Link[index].Km = 0.02517 * value / SQR(Link[index].Diam) /
|
|
3851
4125
|
SQR(Link[index].Diam);
|
|
3852
4126
|
}
|
|
@@ -3857,29 +4131,31 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu
|
|
|
3857
4131
|
// Cannot set status for a check valve
|
|
3858
4132
|
if (Link[index].Type == CVPIPE) return 207;
|
|
3859
4133
|
s = (char)ROUND(value);
|
|
3860
|
-
if (s < 0 || s >
|
|
4134
|
+
if (s < 0 || s > 2) return 211;
|
|
4135
|
+
s = s + CLOSED;
|
|
3861
4136
|
if (property == EN_INITSTATUS)
|
|
3862
4137
|
{
|
|
3863
|
-
|
|
4138
|
+
Link[index].InitStatus = s;
|
|
3864
4139
|
}
|
|
3865
4140
|
else
|
|
3866
4141
|
{
|
|
3867
|
-
setlinkstatus(p, index, s, &hyd->LinkStatus[index], &LinkSetting[index]);
|
|
4142
|
+
setlinkstatus(p, index, s, &hyd->LinkStatus[index], &hyd->LinkSetting[index]);
|
|
3868
4143
|
}
|
|
3869
4144
|
break;
|
|
3870
4145
|
|
|
3871
4146
|
case EN_INITSETTING:
|
|
3872
4147
|
case EN_SETTING:
|
|
3873
|
-
if (value < 0.0) return 211;
|
|
3874
4148
|
if (Link[index].Type == PIPE || Link[index].Type == CVPIPE)
|
|
3875
4149
|
{
|
|
3876
|
-
|
|
4150
|
+
EN_setlinkvalue(p, index, EN_ROUGHNESS, value);
|
|
4151
|
+
if (property == EN_INITSETTING) Link[index].InitSetting = Link[index].Kc;
|
|
3877
4152
|
}
|
|
3878
4153
|
else
|
|
3879
4154
|
{
|
|
3880
4155
|
switch (Link[index].Type)
|
|
3881
4156
|
{
|
|
3882
4157
|
case PUMP:
|
|
4158
|
+
if (value < 0.0) return 211;
|
|
3883
4159
|
break;
|
|
3884
4160
|
case PRV:
|
|
3885
4161
|
case PSV:
|
|
@@ -3890,6 +4166,7 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu
|
|
|
3890
4166
|
value /= Ucf[FLOW];
|
|
3891
4167
|
break;
|
|
3892
4168
|
case TCV:
|
|
4169
|
+
case PCV:
|
|
3893
4170
|
break;
|
|
3894
4171
|
case GPV:
|
|
3895
4172
|
return 207; // Cannot modify setting for GPV
|
|
@@ -3898,12 +4175,13 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu
|
|
|
3898
4175
|
}
|
|
3899
4176
|
if (property == EN_INITSETTING)
|
|
3900
4177
|
{
|
|
3901
|
-
|
|
4178
|
+
Link[index].Kc = value;
|
|
4179
|
+
Link[index].InitSetting = value;
|
|
3902
4180
|
}
|
|
3903
4181
|
else
|
|
3904
4182
|
{
|
|
3905
4183
|
setlinksetting(p, index, value, &hyd->LinkStatus[index],
|
|
3906
|
-
&LinkSetting[index]);
|
|
4184
|
+
&hyd->LinkSetting[index]);
|
|
3907
4185
|
}
|
|
3908
4186
|
}
|
|
3909
4187
|
break;
|
|
@@ -3942,11 +4220,6 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu
|
|
|
3942
4220
|
net->Pump[pumpIndex].Ptype = CONST_HP;
|
|
3943
4221
|
net->Pump[pumpIndex].Hcurve = 0;
|
|
3944
4222
|
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];
|
|
3950
4223
|
}
|
|
3951
4224
|
break;
|
|
3952
4225
|
|
|
@@ -3985,6 +4258,43 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu
|
|
|
3985
4258
|
net->Pump[pumpIndex].Epat = patIndex;
|
|
3986
4259
|
}
|
|
3987
4260
|
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
|
|
3988
4298
|
|
|
3989
4299
|
default:
|
|
3990
4300
|
return 251;
|
|
@@ -4043,20 +4353,20 @@ int DLLEXPORT EN_getvertexcount(EN_Project p, int index, int *count)
|
|
|
4043
4353
|
*/
|
|
4044
4354
|
{
|
|
4045
4355
|
Network *net = &p->network;
|
|
4046
|
-
|
|
4356
|
+
|
|
4047
4357
|
Slink *Link = net->Link;
|
|
4048
4358
|
Pvertices vertices;
|
|
4049
|
-
|
|
4359
|
+
|
|
4050
4360
|
// Check that link exists
|
|
4051
4361
|
*count = 0;
|
|
4052
4362
|
if (!p->Openflag) return 102;
|
|
4053
4363
|
if (index <= 0 || index > net->Nlinks) return 204;
|
|
4054
|
-
|
|
4364
|
+
|
|
4055
4365
|
// Set count to number of vertices
|
|
4056
4366
|
vertices = Link[index].Vertices;
|
|
4057
4367
|
if (vertices) *count = vertices->Npts;
|
|
4058
4368
|
return 0;
|
|
4059
|
-
}
|
|
4369
|
+
}
|
|
4060
4370
|
|
|
4061
4371
|
int DLLEXPORT EN_getvertex(EN_Project p, int index, int vertex, double *x, double *y)
|
|
4062
4372
|
/*----------------------------------------------------------------
|
|
@@ -4070,25 +4380,54 @@ int DLLEXPORT EN_getvertex(EN_Project p, int index, int vertex, double *x, doubl
|
|
|
4070
4380
|
*/
|
|
4071
4381
|
{
|
|
4072
4382
|
Network *net = &p->network;
|
|
4073
|
-
|
|
4383
|
+
|
|
4074
4384
|
Slink *Link = net->Link;
|
|
4075
4385
|
Pvertices vertices;
|
|
4076
|
-
|
|
4386
|
+
|
|
4077
4387
|
// Check that link exists
|
|
4078
4388
|
*x = MISSING;
|
|
4079
4389
|
*y = MISSING;
|
|
4080
4390
|
if (!p->Openflag) return 102;
|
|
4081
4391
|
if (index <= 0 || index > net->Nlinks) return 204;
|
|
4082
|
-
|
|
4392
|
+
|
|
4083
4393
|
// Check that vertex exists
|
|
4084
4394
|
vertices = Link[index].Vertices;
|
|
4085
4395
|
if (vertices == NULL) return 255;
|
|
4086
4396
|
if (vertex <= 0 || vertex > vertices->Npts) return 255;
|
|
4087
4397
|
*x = vertices->X[vertex - 1];
|
|
4088
|
-
*y = vertices->Y[vertex - 1];
|
|
4398
|
+
*y = vertices->Y[vertex - 1];
|
|
4089
4399
|
return 0;
|
|
4090
4400
|
}
|
|
4091
|
-
|
|
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;
|
|
4428
|
+
return 0;
|
|
4429
|
+
}
|
|
4430
|
+
|
|
4092
4431
|
int DLLEXPORT EN_setvertices(EN_Project p, int index, double *x, double *y, int count)
|
|
4093
4432
|
/*----------------------------------------------------------------
|
|
4094
4433
|
** Input: index = link index
|
|
@@ -4101,11 +4440,11 @@ int DLLEXPORT EN_setvertices(EN_Project p, int index, double *x, double *y, int
|
|
|
4101
4440
|
*/
|
|
4102
4441
|
{
|
|
4103
4442
|
Network *net = &p->network;
|
|
4104
|
-
|
|
4443
|
+
|
|
4105
4444
|
Slink *link;
|
|
4106
4445
|
int i;
|
|
4107
4446
|
int err = 0;
|
|
4108
|
-
|
|
4447
|
+
|
|
4109
4448
|
// Check that link exists
|
|
4110
4449
|
if (!p->Openflag) return 102;
|
|
4111
4450
|
if (index <= 0 || index > net->Nlinks) return 204;
|
|
@@ -4113,7 +4452,7 @@ int DLLEXPORT EN_setvertices(EN_Project p, int index, double *x, double *y, int
|
|
|
4113
4452
|
|
|
4114
4453
|
// Delete existing set of vertices
|
|
4115
4454
|
freelinkvertices(link);
|
|
4116
|
-
|
|
4455
|
+
|
|
4117
4456
|
// Add each new vertex to the link
|
|
4118
4457
|
for (i = 0; i < count; i++)
|
|
4119
4458
|
{
|
|
@@ -4122,7 +4461,7 @@ int DLLEXPORT EN_setvertices(EN_Project p, int index, double *x, double *y, int
|
|
|
4122
4461
|
}
|
|
4123
4462
|
if (err) freelinkvertices(link);
|
|
4124
4463
|
return err;
|
|
4125
|
-
}
|
|
4464
|
+
}
|
|
4126
4465
|
|
|
4127
4466
|
/********************************************************************
|
|
4128
4467
|
|
|
@@ -4188,10 +4527,7 @@ int DLLEXPORT EN_setheadcurveindex(EN_Project p, int linkIndex, int curveIndex)
|
|
|
4188
4527
|
{
|
|
4189
4528
|
Network *net = &p->network;
|
|
4190
4529
|
|
|
4191
|
-
double *Ucf = p->Ucf;
|
|
4192
4530
|
int pumpIndex;
|
|
4193
|
-
int oldCurveIndex;
|
|
4194
|
-
int newCurveType;
|
|
4195
4531
|
int err = 0;
|
|
4196
4532
|
Spump *pump;
|
|
4197
4533
|
|
|
@@ -4201,43 +4537,12 @@ int DLLEXPORT EN_setheadcurveindex(EN_Project p, int linkIndex, int curveIndex)
|
|
|
4201
4537
|
if (PUMP != net->Link[linkIndex].Type) return 0;
|
|
4202
4538
|
if (curveIndex < 0 || curveIndex > net->Ncurves) return 206;
|
|
4203
4539
|
|
|
4204
|
-
// Save values that need to be restored in case new curve is invalid
|
|
4205
|
-
pumpIndex = findpump(net, linkIndex);
|
|
4206
|
-
pump = &p->network.Pump[pumpIndex];
|
|
4207
|
-
oldCurveIndex = pump->Hcurve;
|
|
4208
|
-
newCurveType = p->network.Curve[curveIndex].Type;
|
|
4209
|
-
|
|
4210
4540
|
// Assign the new curve to the pump
|
|
4211
|
-
|
|
4541
|
+
pumpIndex = findpump(net, linkIndex);
|
|
4542
|
+
pump = &net->Pump[pumpIndex];
|
|
4212
4543
|
pump->Hcurve = curveIndex;
|
|
4213
|
-
|
|
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;
|
|
4544
|
+
net->Link[linkIndex].Km = 0.0;
|
|
4545
|
+
return 0;
|
|
4241
4546
|
}
|
|
4242
4547
|
|
|
4243
4548
|
/********************************************************************
|
|
@@ -4246,7 +4551,7 @@ int DLLEXPORT EN_setheadcurveindex(EN_Project p, int linkIndex, int curveIndex)
|
|
|
4246
4551
|
|
|
4247
4552
|
********************************************************************/
|
|
4248
4553
|
|
|
4249
|
-
int DLLEXPORT EN_addpattern(EN_Project p, char *id)
|
|
4554
|
+
int DLLEXPORT EN_addpattern(EN_Project p, const char *id)
|
|
4250
4555
|
/*----------------------------------------------------------------
|
|
4251
4556
|
** Input: id = time pattern ID name
|
|
4252
4557
|
** Output: none
|
|
@@ -4294,6 +4599,70 @@ int DLLEXPORT EN_addpattern(EN_Project p, char *id)
|
|
|
4294
4599
|
return 0;
|
|
4295
4600
|
}
|
|
4296
4601
|
|
|
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
|
+
|
|
4297
4666
|
int DLLEXPORT EN_deletepattern(EN_Project p, int index)
|
|
4298
4667
|
/*----------------------------------------------------------------
|
|
4299
4668
|
** Input: index = index of the pattern to delete
|
|
@@ -4323,6 +4692,10 @@ int DLLEXPORT EN_deletepattern(EN_Project p, int index)
|
|
|
4323
4692
|
if (hyd->Epat == index) hyd->Epat = 0;
|
|
4324
4693
|
else if (hyd->Epat > index) hyd->Epat--;
|
|
4325
4694
|
|
|
4695
|
+
// Modify global default demand pattern
|
|
4696
|
+
if (hyd->DefPat == index) hyd->DefPat = 0;
|
|
4697
|
+
else if (hyd->DefPat > index) hyd->DefPat--;
|
|
4698
|
+
|
|
4326
4699
|
// Free the pattern's factor array
|
|
4327
4700
|
FREE(net->Pattern[index].F);
|
|
4328
4701
|
FREE(net->Pattern[index].Comment);
|
|
@@ -4334,7 +4707,7 @@ int DLLEXPORT EN_deletepattern(EN_Project p, int index)
|
|
|
4334
4707
|
return 0;
|
|
4335
4708
|
}
|
|
4336
4709
|
|
|
4337
|
-
int DLLEXPORT EN_getpatternindex(EN_Project p, char *id, int *index)
|
|
4710
|
+
int DLLEXPORT EN_getpatternindex(EN_Project p, const char *id, int *index)
|
|
4338
4711
|
/*----------------------------------------------------------------
|
|
4339
4712
|
** Input: id = time pattern name
|
|
4340
4713
|
** Output: index = time pattern index
|
|
@@ -4375,7 +4748,7 @@ int DLLEXPORT EN_getpatternid(EN_Project p, int index, char *id)
|
|
|
4375
4748
|
return 0;
|
|
4376
4749
|
}
|
|
4377
4750
|
|
|
4378
|
-
int DLLEXPORT EN_setpatternid(EN_Project p, int index, char *id)
|
|
4751
|
+
int DLLEXPORT EN_setpatternid(EN_Project p, int index, const char *id)
|
|
4379
4752
|
/*----------------------------------------------------------------
|
|
4380
4753
|
** Input: index = time pattern index
|
|
4381
4754
|
** id = time pattern ID name
|
|
@@ -4472,7 +4845,7 @@ int DLLEXPORT EN_getaveragepatternvalue(EN_Project p, int index, double *value)
|
|
|
4472
4845
|
|
|
4473
4846
|
*value = 0.0;
|
|
4474
4847
|
if (!p->Openflag) return 102;
|
|
4475
|
-
if (index <
|
|
4848
|
+
if (index < 0 || index > net->Npats) return 205;
|
|
4476
4849
|
for (i = 0; i < Pattern[index].Length; i++)
|
|
4477
4850
|
{
|
|
4478
4851
|
*value += (double)Pattern[index].F[i];
|
|
@@ -4519,7 +4892,7 @@ int DLLEXPORT EN_setpattern(EN_Project p, int index, double *values, int len)
|
|
|
4519
4892
|
|
|
4520
4893
|
********************************************************************/
|
|
4521
4894
|
|
|
4522
|
-
int DLLEXPORT EN_addcurve(EN_Project p, char *id)
|
|
4895
|
+
int DLLEXPORT EN_addcurve(EN_Project p, const char *id)
|
|
4523
4896
|
/*----------------------------------------------------------------
|
|
4524
4897
|
** Input: id = data curve ID name
|
|
4525
4898
|
** Output: none
|
|
@@ -4611,7 +4984,7 @@ int DLLEXPORT EN_deletecurve(EN_Project p, int index)
|
|
|
4611
4984
|
return 0;
|
|
4612
4985
|
}
|
|
4613
4986
|
|
|
4614
|
-
int DLLEXPORT EN_getcurveindex(EN_Project p, char *id, int *index)
|
|
4987
|
+
int DLLEXPORT EN_getcurveindex(EN_Project p, const char *id, int *index)
|
|
4615
4988
|
/*----------------------------------------------------------------
|
|
4616
4989
|
** Input: id = data curve name
|
|
4617
4990
|
** Output: index = data curve index
|
|
@@ -4643,7 +5016,7 @@ int DLLEXPORT EN_getcurveid(EN_Project p, int index, char *id)
|
|
|
4643
5016
|
return 0;
|
|
4644
5017
|
}
|
|
4645
5018
|
|
|
4646
|
-
int DLLEXPORT EN_setcurveid(EN_Project p, int index, char *id)
|
|
5019
|
+
int DLLEXPORT EN_setcurveid(EN_Project p, int index, const char *id)
|
|
4647
5020
|
/*----------------------------------------------------------------
|
|
4648
5021
|
** Input: index = data curve index
|
|
4649
5022
|
** id = data curve ID name
|
|
@@ -4699,6 +5072,23 @@ int DLLEXPORT EN_getcurvetype(EN_Project p, int index, int *type)
|
|
|
4699
5072
|
return 0;
|
|
4700
5073
|
}
|
|
4701
5074
|
|
|
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
|
+
|
|
4702
5092
|
int DLLEXPORT EN_getcurvevalue(EN_Project p, int curveIndex, int pointIndex,
|
|
4703
5093
|
double *x, double *y)
|
|
4704
5094
|
/*----------------------------------------------------------------
|
|
@@ -4768,9 +5158,7 @@ int DLLEXPORT EN_setcurvevalue(EN_Project p, int curveIndex, int pointIndex,
|
|
|
4768
5158
|
// Insert new point into curve
|
|
4769
5159
|
curve->X[n] = x;
|
|
4770
5160
|
curve->Y[n] = y;
|
|
4771
|
-
|
|
4772
|
-
// Adjust parameters for pumps using curve as a head curve
|
|
4773
|
-
return adjustpumpparams(p, curveIndex);
|
|
5161
|
+
return 0;
|
|
4774
5162
|
}
|
|
4775
5163
|
|
|
4776
5164
|
int DLLEXPORT EN_getcurve(EN_Project p, int index, char *id, int *nPoints,
|
|
@@ -4842,9 +5230,7 @@ int DLLEXPORT EN_setcurve(EN_Project p, int index, double *xValues,
|
|
|
4842
5230
|
curve->X[j] = xValues[j];
|
|
4843
5231
|
curve->Y[j] = yValues[j];
|
|
4844
5232
|
}
|
|
4845
|
-
|
|
4846
|
-
// Adjust parameters for pumps using curve as a head curve
|
|
4847
|
-
return adjustpumpparams(p, index);
|
|
5233
|
+
return 0;
|
|
4848
5234
|
}
|
|
4849
5235
|
|
|
4850
5236
|
/********************************************************************
|
|
@@ -4870,84 +5256,30 @@ int DLLEXPORT EN_addcontrol(EN_Project p, int type, int linkIndex, double settin
|
|
|
4870
5256
|
*/
|
|
4871
5257
|
{
|
|
4872
5258
|
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;
|
|
4881
5259
|
|
|
5260
|
+
int err, n;
|
|
5261
|
+
Scontrol ctrl;
|
|
4882
5262
|
|
|
4883
5263
|
// Check that project exists
|
|
4884
5264
|
if (!p->Openflag) return 102;
|
|
4885
5265
|
|
|
4886
5266
|
// Check that controlled link exists
|
|
4887
5267
|
if (linkIndex <= 0 || linkIndex > net->Nlinks) return 204;
|
|
4888
|
-
|
|
4889
|
-
//
|
|
4890
|
-
|
|
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;
|
|
5268
|
+
|
|
5269
|
+
// Insert control properties into a temporary struct
|
|
5270
|
+
err = setcontrol(p, type, linkIndex, setting, nodeIndex, level, &ctrl);
|
|
5271
|
+
if (err > 0) return err;
|
|
4933
5272
|
|
|
4934
5273
|
// Expand project's array of controls
|
|
4935
5274
|
n = net->Ncontrols + 1;
|
|
4936
5275
|
net->Control = (Scontrol *)realloc(net->Control, (n + 1) * sizeof(Scontrol));
|
|
4937
5276
|
|
|
4938
5277
|
// Set properties of the new control
|
|
4939
|
-
|
|
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;
|
|
5278
|
+
net->Control[n] = ctrl;
|
|
4947
5279
|
|
|
4948
5280
|
// Update number of controls
|
|
4949
5281
|
net->Ncontrols = n;
|
|
4950
|
-
parser
|
|
5282
|
+
p->parser.MaxControls = n;
|
|
4951
5283
|
|
|
4952
5284
|
// Replace the control's index
|
|
4953
5285
|
*index = n;
|
|
@@ -5030,8 +5362,8 @@ int DLLEXPORT EN_getcontrol(EN_Project p, int index, int *type, int *linkIndex,
|
|
|
5030
5362
|
break;
|
|
5031
5363
|
}
|
|
5032
5364
|
}
|
|
5033
|
-
else if (control->Status == OPEN) s =
|
|
5034
|
-
else s =
|
|
5365
|
+
else if (control->Status == OPEN) s = SET_OPEN;
|
|
5366
|
+
else s = SET_CLOSED;
|
|
5035
5367
|
|
|
5036
5368
|
// Retrieve level value for a node level control
|
|
5037
5369
|
*nodeIndex = control->Node;
|
|
@@ -5053,8 +5385,8 @@ int DLLEXPORT EN_getcontrol(EN_Project p, int index, int *type, int *linkIndex,
|
|
|
5053
5385
|
{
|
|
5054
5386
|
lvl = (double)control->Time;
|
|
5055
5387
|
}
|
|
5056
|
-
*setting =
|
|
5057
|
-
*level =
|
|
5388
|
+
*setting = s;
|
|
5389
|
+
*level = lvl;
|
|
5058
5390
|
return 0;
|
|
5059
5391
|
}
|
|
5060
5392
|
|
|
@@ -5076,81 +5408,63 @@ int DLLEXPORT EN_setcontrol(EN_Project p, int index, int type, int linkIndex,
|
|
|
5076
5408
|
{
|
|
5077
5409
|
Network *net = &p->network;
|
|
5078
5410
|
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
double s = setting, lvl = level;
|
|
5082
|
-
double *Ucf = p->Ucf;
|
|
5083
|
-
Slink *link;
|
|
5084
|
-
Scontrol *control;
|
|
5411
|
+
int err;
|
|
5412
|
+
Scontrol ctrl;
|
|
5085
5413
|
|
|
5086
5414
|
// Check that project exists
|
|
5087
5415
|
if (!p->Openflag) return 102;
|
|
5088
5416
|
|
|
5089
5417
|
// Check that control exists
|
|
5090
5418
|
if (index <= 0 || index > net->Ncontrols) return 241;
|
|
5091
|
-
control = &net->Control[index];
|
|
5092
5419
|
|
|
5093
5420
|
// Check that controlled link exists (0 index de-activates the control)
|
|
5094
5421
|
if (linkIndex == 0)
|
|
5095
5422
|
{
|
|
5096
|
-
|
|
5423
|
+
net->Control[index].Link = 0;
|
|
5097
5424
|
return 0;
|
|
5098
5425
|
}
|
|
5099
5426
|
if (linkIndex < 0 || linkIndex > net->Nlinks) return 204;
|
|
5100
5427
|
|
|
5101
|
-
//
|
|
5102
|
-
|
|
5428
|
+
// Assign new set of properties to control
|
|
5429
|
+
err = setcontrol(p, type, linkIndex, setting, nodeIndex, level, &ctrl);
|
|
5430
|
+
if (err > 0) return err;
|
|
5431
|
+
net->Control[index] = ctrl;
|
|
5432
|
+
return 0;
|
|
5433
|
+
}
|
|
5103
5434
|
|
|
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;
|
|
5112
5435
|
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
if (
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
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;
|
|
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
|
+
}
|
|
5451
|
+
|
|
5452
|
+
|
|
5453
|
+
int DLLEXPORT EN_setcontrolenabled(EN_Project p, int index, int enabled)
|
|
5454
|
+
{
|
|
5455
|
+
Network *net = &p->network;
|
|
5456
|
+
Scontrol *control;
|
|
5457
|
+
|
|
5458
|
+
// Check for valid arguments
|
|
5459
|
+
if (enabled != TRUE && enabled != FALSE)
|
|
5460
|
+
return 202; // illegal numeric value
|
|
5461
|
+
if (!p->Openflag)
|
|
5462
|
+
return 102;
|
|
5463
|
+
if (index <= 0 || index > net->Ncontrols)
|
|
5464
|
+
return 241;
|
|
5465
|
+
|
|
5466
|
+
control = &net->Control[index];
|
|
5467
|
+
control->isEnabled = enabled;
|
|
5154
5468
|
return 0;
|
|
5155
5469
|
}
|
|
5156
5470
|
|
|
@@ -5404,7 +5718,7 @@ int DLLEXPORT EN_setpremisestatus(EN_Project p, int ruleIndex, int premiseIndex,
|
|
|
5404
5718
|
** Input: ruleIndex = rule index
|
|
5405
5719
|
** premiseIndex = premise index
|
|
5406
5720
|
** status = object status being tested against
|
|
5407
|
-
** (see EN_RuleStatus)
|
|
5721
|
+
** (see EN_RuleStatus)
|
|
5408
5722
|
** Output: none
|
|
5409
5723
|
** Returns: error code
|
|
5410
5724
|
** Purpose: sets the status of an object being tested against
|
|
@@ -5456,7 +5770,7 @@ int DLLEXPORT EN_getthenaction(EN_Project p, int ruleIndex, int actionIndex,
|
|
|
5456
5770
|
** Input: ruleIndex = rule index
|
|
5457
5771
|
** actionIndex = index of a rule's THEN actions
|
|
5458
5772
|
** Output: linkIndex = index of link appearing in the action
|
|
5459
|
-
** status = status assigned to the link (see EN_RuleStatus)
|
|
5773
|
+
** status = status assigned to the link (see EN_RuleStatus)
|
|
5460
5774
|
** setting = setting assigned to the link
|
|
5461
5775
|
** Returns: error code
|
|
5462
5776
|
** Purpose: retrieves the properties of a rule's THEN action
|
|
@@ -5484,7 +5798,7 @@ int DLLEXPORT EN_setthenaction(EN_Project p, int ruleIndex, int actionIndex,
|
|
|
5484
5798
|
** Input: ruleIndex = rule index
|
|
5485
5799
|
** actionIndex = index of a rule's THEN actions
|
|
5486
5800
|
** linkIndex = index of link appearing in the action
|
|
5487
|
-
** status = status assigned to the link (see EN_RuleStatus)
|
|
5801
|
+
** status = status assigned to the link (see EN_RuleStatus)
|
|
5488
5802
|
** setting = setting assigned to the link
|
|
5489
5803
|
** Returns: error code
|
|
5490
5804
|
** Purpose: sets the properties of a rule's THEN action
|
|
@@ -5512,7 +5826,7 @@ int DLLEXPORT EN_getelseaction(EN_Project p, int ruleIndex, int actionIndex,
|
|
|
5512
5826
|
** Input: ruleIndex = rule index
|
|
5513
5827
|
** actionIndex = index of a rule's ELSE actions
|
|
5514
5828
|
** Output: linkIndex = index of link appearing in the action
|
|
5515
|
-
** status = status assigned to the link (see EN_RuleStatus)
|
|
5829
|
+
** status = status assigned to the link (see EN_RuleStatus)
|
|
5516
5830
|
** setting = setting assigned to the link
|
|
5517
5831
|
** Returns: error code
|
|
5518
5832
|
** Purpose: retrieves the properties of a rule's ELSE action
|
|
@@ -5540,7 +5854,7 @@ int DLLEXPORT EN_setelseaction(EN_Project p, int ruleIndex, int actionIndex,
|
|
|
5540
5854
|
** Input: ruleIndex = rule index
|
|
5541
5855
|
** actionIndex = index of a rule's ELSE actions
|
|
5542
5856
|
** linkIndex = index of link appearing in the action
|
|
5543
|
-
** status = status assigned to the link (see EN_RuleStatus)
|
|
5857
|
+
** status = status assigned to the link (see EN_RuleStatus)
|
|
5544
5858
|
** setting = setting assigned to the link
|
|
5545
5859
|
** Returns: error code
|
|
5546
5860
|
** Purpose: sets the properties of a rule's ELSE action
|
|
@@ -5576,3 +5890,41 @@ int DLLEXPORT EN_setrulepriority(EN_Project p, int index, double priority)
|
|
|
5576
5890
|
p->network.Rule[index].priority = priority;
|
|
5577
5891
|
return 0;
|
|
5578
5892
|
}
|
|
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
|
+
|