Merge pull request #7 from samhatchett/next

Next
This commit is contained in:
Sam Hatchett
2013-09-30 13:30:18 -07:00
17 changed files with 451 additions and 392 deletions

0
.gitignore vendored Normal file → Executable file
View File

0
README.md Normal file → Executable file
View File

0
build/MSVS/LemonTigerJ.sln Normal file → Executable file
View File

0
build/MSVS/LemonTigerJ.vcxproj Normal file → Executable file
View File

20
build/Xcode/epanet/epanet.xcodeproj/project.pbxproj Normal file → Executable file
View File

@@ -40,7 +40,7 @@
22322FA41068369500641384 /* report.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7E1068369500641384 /* report.c */; }; 22322FA41068369500641384 /* report.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7E1068369500641384 /* report.c */; };
22322FA51068369500641384 /* rules.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7F1068369500641384 /* rules.c */; }; 22322FA51068369500641384 /* rules.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7F1068369500641384 /* rules.c */; };
22322FA61068369500641384 /* smatrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F801068369500641384 /* smatrix.c */; }; 22322FA61068369500641384 /* smatrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F801068369500641384 /* smatrix.c */; };
22322FAA106836BC00641384 /* epanet2.h in Headers */ = {isa = PBXBuildFile; fileRef = 22322FA9106836B000641384 /* epanet2.h */; }; 22322FAA106836BC00641384 /* epanet2.h in Headers */ = {isa = PBXBuildFile; fileRef = 22322FA9106836B000641384 /* epanet2.h */; settings = {ATTRIBUTES = (Public, ); }; };
2255753F17551234009946B1 /* epanet.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F711068369500641384 /* epanet.c */; }; 2255753F17551234009946B1 /* epanet.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F711068369500641384 /* epanet.c */; };
2255754017551234009946B1 /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F731068369500641384 /* hash.c */; }; 2255754017551234009946B1 /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F731068369500641384 /* hash.c */; };
2255754117551234009946B1 /* hydraul.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F751068369500641384 /* hydraul.c */; }; 2255754117551234009946B1 /* hydraul.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F751068369500641384 /* hydraul.c */; };
@@ -54,6 +54,7 @@
2255754917551234009946B1 /* report.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7E1068369500641384 /* report.c */; }; 2255754917551234009946B1 /* report.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7E1068369500641384 /* report.c */; };
2255754A17551234009946B1 /* rules.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7F1068369500641384 /* rules.c */; }; 2255754A17551234009946B1 /* rules.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F7F1068369500641384 /* rules.c */; };
2255754B17551234009946B1 /* smatrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F801068369500641384 /* smatrix.c */; }; 2255754B17551234009946B1 /* smatrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22322F801068369500641384 /* smatrix.c */; };
226537E0179EDEEB00258C60 /* epanet2.h in Headers */ = {isa = PBXBuildFile; fileRef = 22322FA9106836B000641384 /* epanet2.h */; settings = {ATTRIBUTES = (Public, ); }; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@@ -180,6 +181,7 @@
isa = PBXHeadersBuildPhase; isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
226537E0179EDEEB00258C60 /* epanet2.h in Headers */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -258,7 +260,7 @@
08FB7793FE84155DC02AAC07 /* Project object */ = { 08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 0460; LastUpgradeCheck = 0500;
}; };
buildConfigurationList = 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "epanet" */; buildConfigurationList = 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "epanet" */;
compatibilityVersion = "Xcode 3.2"; compatibilityVersion = "Xcode 3.2";
@@ -390,16 +392,20 @@
1DEB914F08733D8E0010E9CD /* Debug */ = { 1DEB914F08733D8E0010E9CD /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_OPTIMIZATION_LEVEL = 0; GCC_OPTIMIZATION_LEVEL = 0;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = macinclude; HEADER_SEARCH_PATHS = macinclude;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
@@ -410,15 +416,19 @@
1DEB915008733D8E0010E9CD /* Release */ = { 1DEB915008733D8E0010E9CD /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = macinclude; HEADER_SEARCH_PATHS = macinclude;
SDKROOT = ""; SDKROOT = "";
@@ -461,7 +471,6 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_EMPTY_BODY = YES;
@@ -482,7 +491,6 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_EMPTY_BODY = YES;

View File

143
include/epanet2.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/* /*
******************************************************************* *******************************************************************
TOOLKIT.H - Prototypes for EPANET Functions Exported to DLL Toolkit EPANET2.H - Prototypes for EPANET Functions Exported to DLL Toolkit
VERSION: 2.00 VERSION: 2.00
DATE: 5/8/00 DATE: 5/8/00
@@ -9,8 +9,8 @@
3/1/01 3/1/01
8/15/07 (2.00.11) 8/15/07 (2.00.11)
2/14/08 (2.00.12) 2/14/08 (2.00.12)
AUTHOR: L. Rossman AUTHORS: L. Rossman - US EPA - NRMRL
US EPA - NRMRL OpenWaterAnalytics members: see git stats for contributors
******************************************************************* *******************************************************************
*/ */
@@ -177,96 +177,81 @@
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
int DLLEXPORT ENepanet(char *, char *, char *, void (*) (char *)); int DLLEXPORT ENepanet(char *inpFile, char *rptFile, char *binOutFile, void (*callback) (char *));
int DLLEXPORT ENopen(char *, char *, char *); int DLLEXPORT ENopen(char *inpFile, char *rptFile, char *binOutFile);
int DLLEXPORT ENsaveinpfile(char *); int DLLEXPORT ENsaveinpfile(char *filename);
int DLLEXPORT ENclose(void); int DLLEXPORT ENclose();
int DLLEXPORT ENsolveH(void); int DLLEXPORT ENsolveH();
int DLLEXPORT ENsaveH(void); int DLLEXPORT ENsaveH();
int DLLEXPORT ENopenH(void); int DLLEXPORT ENopenH();
int DLLEXPORT ENinitH(int); int DLLEXPORT ENinitH(int initFlag);
int DLLEXPORT ENrunH(long *); int DLLEXPORT ENrunH(long *currentTime);
int DLLEXPORT ENnextH(long *tstep); int DLLEXPORT ENnextH(long *tStep);
int DLLEXPORT ENcloseH(void); int DLLEXPORT ENcloseH();
int DLLEXPORT ENsavehydfile(char *); int DLLEXPORT ENsavehydfile(char *filename);
int DLLEXPORT ENusehydfile(char *); int DLLEXPORT ENusehydfile(char *filename);
int DLLEXPORT ENsolveQ(void); int DLLEXPORT ENsolveQ();
int DLLEXPORT ENopenQ(void); int DLLEXPORT ENopenQ();
int DLLEXPORT ENinitQ(int); int DLLEXPORT ENinitQ(int saveFlag);
int DLLEXPORT ENrunQ(long *); int DLLEXPORT ENrunQ(long *currentTime);
int DLLEXPORT ENnextQ(long *); int DLLEXPORT ENnextQ(long *tStep);
int DLLEXPORT ENstepQ(long *); int DLLEXPORT ENstepQ(long *timeLeft);
int DLLEXPORT ENcloseQ(void); int DLLEXPORT ENcloseQ();
int DLLEXPORT ENwriteline(char *); int DLLEXPORT ENwriteline(char *line);
int DLLEXPORT ENreport(void); int DLLEXPORT ENreport();
int DLLEXPORT ENresetreport(void); int DLLEXPORT ENresetreport();
int DLLEXPORT ENsetreport(char *); int DLLEXPORT ENsetreport(char *reportFormat);
int DLLEXPORT ENgetcontrol(int, int *, int *, EN_API_FLOAT_TYPE *, int DLLEXPORT ENgetcontrol(int controlIndex, int *controlType, int *linkIdx, EN_API_FLOAT_TYPE *setting, int *nodeIdx, EN_API_FLOAT_TYPE *level);
int *, EN_API_FLOAT_TYPE *); int DLLEXPORT ENgetcount(int code, int *count);
int DLLEXPORT ENgetcount(int, int *); int DLLEXPORT ENgetoption(int code, EN_API_FLOAT_TYPE *value);
int DLLEXPORT ENgetoption(int, EN_API_FLOAT_TYPE *); int DLLEXPORT ENgettimeparam(int code, long *value);
int DLLEXPORT ENgettimeparam(int, long *); int DLLEXPORT ENgetflowunits(int *code);
int DLLEXPORT ENgetflowunits(int *); int DLLEXPORT ENgetpatternindex(char *id, int *index);
int DLLEXPORT ENgetpatternindex(char *, int *); int DLLEXPORT ENgetpatternid(int index, char *id);
int DLLEXPORT ENgetpatternid(int, char *); int DLLEXPORT ENgetpatternlen(int index, int *len);
int DLLEXPORT ENgetpatternlen(int, int *); int DLLEXPORT ENgetpatternvalue(int index, int period, EN_API_FLOAT_TYPE *value);
int DLLEXPORT ENgetpatternvalue(int, int, EN_API_FLOAT_TYPE *);
int DLLEXPORT ENgetaveragepatternvalue(int index, EN_API_FLOAT_TYPE *value); int DLLEXPORT ENgetaveragepatternvalue(int index, EN_API_FLOAT_TYPE *value);
int DLLEXPORT ENgetqualtype(int *, int *); int DLLEXPORT ENgetqualtype(int *qualcode, int *tracenode);
int DLLEXPORT ENgeterror(int, char *, int); int DLLEXPORT ENgeterror(int errcode, char *errmsg, int maxLen);
int DLLEXPORT ENgetstatistic(int code, int* value); int DLLEXPORT ENgetstatistic(int code, EN_API_FLOAT_TYPE* value);
int DLLEXPORT ENgetnodeindex(char *, int *); int DLLEXPORT ENgetnodeindex(char *id, int *index);
int DLLEXPORT ENgetnodeid(int, char *); int DLLEXPORT ENgetnodeid(int index, char *id);
int DLLEXPORT ENgetnodetype(int, int *); int DLLEXPORT ENgetnodetype(int index, int *code);
int DLLEXPORT ENgetnodevalue(int, int, EN_API_FLOAT_TYPE *); int DLLEXPORT ENgetnodevalue(int index, int code, EN_API_FLOAT_TYPE *value);
int DLLEXPORT ENgetcoord(int , EN_API_FLOAT_TYPE *, EN_API_FLOAT_TYPE *); int DLLEXPORT ENgetcoord(int index, EN_API_FLOAT_TYPE *x, EN_API_FLOAT_TYPE *y);
int DLLEXPORT ENgetnumdemands(int, int *); int DLLEXPORT ENgetnumdemands(int nodeIndex, int *numDemands);
int DLLEXPORT ENgetbasedemand(int, int, EN_API_FLOAT_TYPE *); int DLLEXPORT ENgetbasedemand(int nodeIndex, int demandIdx, EN_API_FLOAT_TYPE *baseDemand);
int DLLEXPORT ENgetdemandpattern(int, int, int *); int DLLEXPORT ENgetdemandpattern(int nodeIndex, int demandIdx, int *pattIdx);
int DLLEXPORT ENgetlinkindex(char *, int *); int DLLEXPORT ENgetlinkindex(char *id, int *index);
int DLLEXPORT ENgetlinkid(int, char *); int DLLEXPORT ENgetlinkid(int index, char *id);
int DLLEXPORT ENgetlinktype(int, int *); int DLLEXPORT ENgetlinktype(int index, int *code);
int DLLEXPORT ENgetlinknodes(int, int *, int *); int DLLEXPORT ENgetlinknodes(int index, int *node1, int *node2);
int DLLEXPORT ENgetlinkvalue(int, int, EN_API_FLOAT_TYPE *); int DLLEXPORT ENgetlinkvalue(int index, int code, EN_API_FLOAT_TYPE *value);
int DLLEXPORT ENgetcurve(int curveIndex, int *nValues, EN_API_FLOAT_TYPE **xValues, EN_API_FLOAT_TYPE **yValues); int DLLEXPORT ENgetcurve(int curveIndex, char* id, int *nValues, EN_API_FLOAT_TYPE **xValues, EN_API_FLOAT_TYPE **yValues);
int DLLEXPORT ENgetversion(int *); int DLLEXPORT ENgetversion(int *version);
int DLLEXPORT ENsetcontrol(int, int, int, EN_API_FLOAT_TYPE, int, EN_API_FLOAT_TYPE); int DLLEXPORT ENsetcontrol(int cindex, int ctype, int lindex, EN_API_FLOAT_TYPE setting, int nindex, EN_API_FLOAT_TYPE level);
int DLLEXPORT ENsetnodevalue(int, int, EN_API_FLOAT_TYPE); int DLLEXPORT ENsetnodevalue(int index, int code, EN_API_FLOAT_TYPE v);
int DLLEXPORT ENsetlinkvalue(int, int, EN_API_FLOAT_TYPE); int DLLEXPORT ENsetlinkvalue(int index, int code, EN_API_FLOAT_TYPE v);
int DLLEXPORT ENaddpattern(char *); int DLLEXPORT ENaddpattern(char *id);
int DLLEXPORT ENsetpattern(int, EN_API_FLOAT_TYPE *, int); int DLLEXPORT ENsetpattern(int index, EN_API_FLOAT_TYPE *f, int len);
int DLLEXPORT ENsetpatternvalue(int, int, EN_API_FLOAT_TYPE); int DLLEXPORT ENsetpatternvalue(int index, int period, EN_API_FLOAT_TYPE value);
int DLLEXPORT ENsettimeparam(int, long); int DLLEXPORT ENsettimeparam(int code, long value);
int DLLEXPORT ENsetoption(int, EN_API_FLOAT_TYPE); int DLLEXPORT ENsetoption(int code, EN_API_FLOAT_TYPE v);
int DLLEXPORT ENsetstatusreport(int); int DLLEXPORT ENsetstatusreport(int code);
int DLLEXPORT ENsetqualtype(int qualcode, char *chemname, char *chemunits, char *tracenode); int DLLEXPORT ENsetqualtype(int qualcode, char *chemname, char *chemunits, char *tracenode);
int DLLEXPORT ENsetbasedemand(int nodeIndex, int demandIdx, EN_API_FLOAT_TYPE baseDemand);
//LemonTiger functions
/* See testLT.c for a LemonTiger test */
//LT equivalent to ENopenH() + ENopenQ() + ENinitH() + ENinitQ()
int DLLEXPORT ENopeninitHQ();
//LT equivalent to ENrunQ() + ENnextQ();
int DLLEXPORT ENrunnextHQ(long*, long*);
//LT equivalent to ENrunQ() + ENstepQ();
int DLLEXPORT ENrunstepHQ(long*, long*);
//LT equivalent to ENcloseH() + ENcloseQ();
int DLLEXPORT ENcloseHQ();
#if defined(__cplusplus) #if defined(__cplusplus)
} }

View File

@@ -1248,7 +1248,7 @@ int DLLEXPORT ENgeterror(int errcode, char *errmsg, int n)
else return(0); else return(0);
} }
int DLLEXPORT ENgetstatistic(int code, int* value) int DLLEXPORT ENgetstatistic(int code, EN_API_FLOAT_TYPE* value)
/*---------------------------------------------------------------- /*----------------------------------------------------------------
** Input: code = type of simulation statistic to retrieve ** Input: code = type of simulation statistic to retrieve
** Output: value = value of requested statistic ** Output: value = value of requested statistic
@@ -1259,10 +1259,10 @@ int DLLEXPORT ENgetstatistic(int code, int* value)
{ {
switch (code) { switch (code) {
case EN_ITERATIONS: case EN_ITERATIONS:
*value = _iterations; *value = (EN_API_FLOAT_TYPE)_iterations;
break; break;
case EN_RELATIVEERROR: case EN_RELATIVEERROR:
*value = _relativeError; *value = (EN_API_FLOAT_TYPE)_relativeError;
break; break;
default: default:
break; break;
@@ -1443,19 +1443,19 @@ int DLLEXPORT ENgetnodevalue(int index, int code, EN_API_FLOAT_TYPE *value)
break; //(2.00.11 - LR) break; //(2.00.11 - LR)
case EN_DEMAND: case EN_DEMAND:
v = D[index]*Ucf[FLOW]; v = NodeDemand[index]*Ucf[FLOW];
break; break;
case EN_HEAD: case EN_HEAD:
v = H[index]*Ucf[HEAD]; v = NodeHead[index]*Ucf[HEAD];
break; break;
case EN_PRESSURE: case EN_PRESSURE:
v = (H[index] - Node[index].El)*Ucf[PRESSURE]; v = (NodeHead[index] - Node[index].El)*Ucf[PRESSURE];
break; break;
case EN_QUALITY: case EN_QUALITY:
v = C[index]*Ucf[QUALITY]; v = NodeQual[index]*Ucf[QUALITY];
break; break;
/*** New parameters added for retrieval begins here ***/ //(2.00.12 - LR) /*** New parameters added for retrieval begins here ***/ //(2.00.12 - LR)
@@ -1492,7 +1492,7 @@ int DLLEXPORT ENgetnodevalue(int index, int code, EN_API_FLOAT_TYPE *value)
v = (Tank[index-Njuncs].Hmin - Node[index].El) * Ucf[ELEV]; v = (Tank[index-Njuncs].Hmin - Node[index].El) * Ucf[ELEV];
} }
break; break;
case EN_MAXLEVEL: case EN_MAXLEVEL:
v = 0.0; v = 0.0;
if ( index > Njuncs ) if ( index > Njuncs )
@@ -1518,7 +1518,7 @@ int DLLEXPORT ENgetnodevalue(int index, int code, EN_API_FLOAT_TYPE *value)
case EN_TANKVOLUME: case EN_TANKVOLUME:
if (index <= Njuncs) return(251); if (index <= Njuncs) return(251);
v = tankvolume(index-Njuncs, H[index])*Ucf[VOLUME]; v = tankvolume(index-Njuncs, NodeHead[index])*Ucf[VOLUME];
break; break;
default: return(251); default: return(251);
@@ -1685,7 +1685,7 @@ int DLLEXPORT ENgetlinkvalue(int index, int code, EN_API_FLOAT_TYPE *value)
case EN_FLOW: case EN_FLOW:
/*** Updated 10/25/00 ***/ /*** Updated 10/25/00 ***/
if (S[index] <= CLOSED) v = 0.0; if (LinkStatus[index] <= CLOSED) v = 0.0;
else v = Q[index]*Ucf[FLOW]; else v = Q[index]*Ucf[FLOW];
break; break;
@@ -1693,7 +1693,7 @@ int DLLEXPORT ENgetlinkvalue(int index, int code, EN_API_FLOAT_TYPE *value)
if (Link[index].Type == PUMP) v = 0.0; if (Link[index].Type == PUMP) v = 0.0;
/*** Updated 11/19/01 ***/ /*** Updated 11/19/01 ***/
else if (S[index] <= CLOSED) v = 0.0; else if (LinkStatus[index] <= CLOSED) v = 0.0;
else else
{ {
@@ -1706,26 +1706,31 @@ int DLLEXPORT ENgetlinkvalue(int index, int code, EN_API_FLOAT_TYPE *value)
case EN_HEADLOSS: case EN_HEADLOSS:
/*** Updated 11/19/01 ***/ /*** Updated 11/19/01 ***/
if (S[index] <= CLOSED) v = 0.0; if (LinkStatus[index] <= CLOSED) v = 0.0;
else else
{ {
h = H[Link[index].N1] - H[Link[index].N2]; h = NodeHead[Link[index].N1] - NodeHead[Link[index].N2];
if (Link[index].Type != PUMP) h = ABS(h); if (Link[index].Type != PUMP) h = ABS(h);
v = h*Ucf[HEADLOSS]; v = h*Ucf[HEADLOSS];
} }
break; break;
case EN_STATUS: case EN_STATUS:
if (S[index] <= CLOSED) v = 0.0; if (LinkStatus[index] <= CLOSED) v = 0.0;
else v = 1.0; else v = 1.0;
break; break;
case EN_SETTING: case EN_SETTING:
if (Link[index].Type == PIPE || Link[index].Type == CV) if (Link[index].Type == PIPE || Link[index].Type == CV) {
return(ENgetlinkvalue(index, EN_ROUGHNESS, value)); return(ENgetlinkvalue(index, EN_ROUGHNESS, value));
if (K[index] == MISSING) v = 0.0; }
else v = K[index]; if (LinkSetting[index] == MISSING) {
v = 0.0;
}
else {
v = LinkSetting[index];
}
switch (Link[index].Type) switch (Link[index].Type)
{ {
case PRV: case PRV:
@@ -1750,7 +1755,7 @@ int DLLEXPORT ENgetlinkvalue(int index, int code, EN_API_FLOAT_TYPE *value)
} }
int DLLEXPORT ENgetcurve(int curveIndex, int *nValues, EN_API_FLOAT_TYPE **xValues, EN_API_FLOAT_TYPE **yValues) int DLLEXPORT ENgetcurve(int curveIndex, char* id, int *nValues, EN_API_FLOAT_TYPE **xValues, EN_API_FLOAT_TYPE **yValues)
/*---------------------------------------------------------------- /*----------------------------------------------------------------
** Input: curveIndex = curve index ** Input: curveIndex = curve index
** Output: *nValues = number of points on curve ** Output: *nValues = number of points on curve
@@ -1776,6 +1781,7 @@ int DLLEXPORT ENgetcurve(int curveIndex, int *nValues, EN_API_FLOAT_TYPE **xVal
pointY[iPoint] = (EN_API_FLOAT_TYPE)y; pointY[iPoint] = (EN_API_FLOAT_TYPE)y;
} }
strncpy(id, curve.ID, MAXID);
*nValues = nPoints; *nValues = nPoints;
*xValues = pointX; *xValues = pointX;
*yValues = pointY; *yValues = pointY;
@@ -1910,7 +1916,7 @@ int DLLEXPORT ENsetnodevalue(int index, int code, EN_API_FLOAT_TYPE v)
Tank[j].Hmin += value; Tank[j].Hmin += value;
Tank[j].Hmax += value; Tank[j].Hmax += value;
Node[index].El += value; Node[index].El += value;
H[index] += value; NodeHead[index] += value;
} }
break; break;
@@ -1967,7 +1973,9 @@ int DLLEXPORT ENsetnodevalue(int index, int code, EN_API_FLOAT_TYPE v)
source->Pat = 0; source->Pat = 0;
Node[index].S = source; Node[index].S = source;
} }
if (code == EN_SOURCEQUAL) source->C0 = value; if (code == EN_SOURCEQUAL) {
source->C0 = value;
}
else if (code == EN_SOURCEPAT) else if (code == EN_SOURCEPAT)
{ {
j = ROUND(value); j = ROUND(value);
@@ -1991,7 +1999,7 @@ int DLLEXPORT ENsetnodevalue(int index, int code, EN_API_FLOAT_TYPE v)
Tank[j].Hmin = Tank[j].H0; Tank[j].Hmin = Tank[j].H0;
Tank[j].Hmax = Tank[j].H0; Tank[j].Hmax = Tank[j].H0;
Node[index].El = Tank[j].H0; Node[index].El = Tank[j].H0;
H[index] = Tank[j].H0; NodeHead[index] = Tank[j].H0;
} }
else else
{ {
@@ -2000,7 +2008,9 @@ int DLLEXPORT ENsetnodevalue(int index, int code, EN_API_FLOAT_TYPE v)
|| value < Tank[j].Hmin) return(202); || value < Tank[j].Hmin) return(202);
Tank[j].H0 = value; Tank[j].H0 = value;
Tank[j].V0 = tankvolume(j, Tank[j].H0); Tank[j].V0 = tankvolume(j, Tank[j].H0);
H[index] = Tank[j].H0; // Resetting Volume in addition to initial volume
Tank[j].V = Tank[j].V0;
NodeHead[index] = Tank[j].H0;
} }
break; break;
@@ -2155,7 +2165,7 @@ int DLLEXPORT ENsetlinkvalue(int index, int code, EN_API_FLOAT_TYPE v)
if (code == EN_INITSTATUS) if (code == EN_INITSTATUS)
setlinkstatus(index, s, &Link[index].Stat, &Link[index].Kc); setlinkstatus(index, s, &Link[index].Stat, &Link[index].Kc);
else else
setlinkstatus(index, s, &S[index], &K[index]); setlinkstatus(index, s, &LinkStatus[index], &LinkSetting[index]);
break; break;
case EN_INITSETTING: case EN_INITSETTING:
@@ -2182,7 +2192,7 @@ int DLLEXPORT ENsetlinkvalue(int index, int code, EN_API_FLOAT_TYPE v)
if (code == EN_INITSETTING) if (code == EN_INITSETTING)
setlinksetting(index, value, &Link[index].Stat, &Link[index].Kc); setlinksetting(index, value, &Link[index].Stat, &Link[index].Kc);
else else
setlinksetting(index, value, &S[index], &K[index]); setlinksetting(index, value, &LinkStatus[index], &LinkSetting[index]);
} }
break; break;
@@ -2750,13 +2760,13 @@ void initpointers()
**---------------------------------------------------------------- **----------------------------------------------------------------
*/ */
{ {
D = NULL; NodeDemand = NULL;
C = NULL; NodeQual = NULL;
H = NULL; NodeHead = NULL;
Q = NULL; Q = NULL;
R = NULL; PipeRateCoeff = NULL;
S = NULL; LinkStatus = NULL;
K = NULL; LinkSetting = NULL;
OldStat = NULL; OldStat = NULL;
Node = NULL; Node = NULL;
@@ -2819,13 +2829,13 @@ int allocdata()
{ {
n = MaxNodes + 1; n = MaxNodes + 1;
Node = (Snode *) calloc(n, sizeof(Snode)); Node = (Snode *) calloc(n, sizeof(Snode));
D = (double *) calloc(n, sizeof(double)); NodeDemand = (double *) calloc(n, sizeof(double));
C = (double *) calloc(n, sizeof(double)); NodeQual = (double *) calloc(n, sizeof(double));
H = (double *) calloc(n, sizeof(double)); NodeHead = (double *) calloc(n, sizeof(double));
ERRCODE(MEMCHECK(Node)); ERRCODE(MEMCHECK(Node));
ERRCODE(MEMCHECK(D)); ERRCODE(MEMCHECK(NodeDemand));
ERRCODE(MEMCHECK(C)); ERRCODE(MEMCHECK(NodeQual));
ERRCODE(MEMCHECK(H)); ERRCODE(MEMCHECK(NodeHead));
} }
/* Allocate memory for network links */ /* Allocate memory for network links */
@@ -2834,12 +2844,12 @@ int allocdata()
n = MaxLinks + 1; n = MaxLinks + 1;
Link = (Slink *) calloc(n, sizeof(Slink)); Link = (Slink *) calloc(n, sizeof(Slink));
Q = (double *) calloc(n, sizeof(double)); Q = (double *) calloc(n, sizeof(double));
K = (double *) calloc(n, sizeof(double)); LinkSetting = (double *) calloc(n, sizeof(double));
S = (char *) calloc(n, sizeof(char)); LinkStatus = (char *) calloc(n, sizeof(char));
ERRCODE(MEMCHECK(Link)); ERRCODE(MEMCHECK(Link));
ERRCODE(MEMCHECK(Q)); ERRCODE(MEMCHECK(Q));
ERRCODE(MEMCHECK(K)); ERRCODE(MEMCHECK(LinkSetting));
ERRCODE(MEMCHECK(S)); ERRCODE(MEMCHECK(LinkStatus));
} }
/* Allocate memory for tanks, sources, pumps, valves, */ /* Allocate memory for tanks, sources, pumps, valves, */
@@ -2950,12 +2960,12 @@ void freedata()
Psource source; Psource source;
/* Free memory for computed results */ /* Free memory for computed results */
free(D); free(NodeDemand);
free(C); free(NodeQual);
free(H); free(NodeHead);
free(Q); free(Q);
free(K); free(LinkSetting);
free(S); free(LinkStatus);
/* Free memory for node data */ /* Free memory for node data */
if (Node != NULL) if (Node != NULL)
@@ -3285,6 +3295,22 @@ int DLLEXPORT ENgetbasedemand(int nodeIndex, int demandIdx, EN_API_FLOAT_TYPE *
} }
return 0; return 0;
} }
int DLLEXPORT ENsetbasedemand(int nodeIndex, int demandIdx, EN_API_FLOAT_TYPE baseDemand)
{
Pdemand d;
int n=1;
/* Check for valid arguments */
if (!Openflag) return(102);
if (nodeIndex <= 0 || nodeIndex > Nnodes) return(203);
if (nodeIndex <= Njuncs) {
for(d=Node[nodeIndex].D; n<demandIdx && d != NULL; d=d->next) n++;
if(n!=demandIdx) return(253);
d->Base = baseDemand/Ucf[FLOW];
}
return 0;
}
int DLLEXPORT ENgetdemandpattern(int nodeIndex, int demandIdx, int *pattIdx) int DLLEXPORT ENgetdemandpattern(int nodeIndex, int demandIdx, int *pattIdx)
{ {
Pdemand d; Pdemand d;

View File

@@ -123,10 +123,10 @@ void inithyd(int initflag)
for (i=1; i<=Ntanks; i++) for (i=1; i<=Ntanks; i++)
{ {
Tank[i].V = Tank[i].V0; Tank[i].V = Tank[i].V0;
H[Tank[i].Node] = Tank[i].H0; NodeHead[Tank[i].Node] = Tank[i].H0;
/*** Updated 10/25/00 ***/ /*** Updated 10/25/00 ***/
D[Tank[i].Node] = 0.0; NodeDemand[Tank[i].Node] = 0.0;
OldStat[Nlinks+i] = TEMPCLOSED; OldStat[Nlinks+i] = TEMPCLOSED;
} }
@@ -140,24 +140,24 @@ void inithyd(int initflag)
for (i=1; i<=Nlinks; i++) for (i=1; i<=Nlinks; i++)
{ {
/* Initialize status and setting */ /* Initialize status and setting */
S[i] = Link[i].Stat; LinkStatus[i] = Link[i].Stat;
K[i] = Link[i].Kc; LinkSetting[i] = Link[i].Kc;
/* Start active control valves in ACTIVE position */ //(2.00.11 - LR) /* Start active control valves in ACTIVE position */ //(2.00.11 - LR)
if ( if (
(Link[i].Type == PRV || Link[i].Type == PSV (Link[i].Type == PRV || Link[i].Type == PSV
|| Link[i].Type == FCV) //(2.00.11 - LR) || Link[i].Type == FCV) //(2.00.11 - LR)
&& (Link[i].Kc != MISSING) && (Link[i].Kc != MISSING)
) S[i] = ACTIVE; //(2.00.11 - LR) ) LinkStatus[i] = ACTIVE; //(2.00.11 - LR)
/*** Updated 3/1/01 ***/ /*** Updated 3/1/01 ***/
/* Initialize flows if necessary */ /* Initialize flows if necessary */
if (S[i] <= CLOSED) Q[i] = QZERO; if (LinkStatus[i] <= CLOSED) Q[i] = QZERO;
else if (ABS(Q[i]) <= QZERO || initflag > 0) else if (ABS(Q[i]) <= QZERO || initflag > 0)
initlinkflow(i, S[i], K[i]); initlinkflow(i, LinkStatus[i], LinkSetting[i]);
/* Save initial status */ /* Save initial status */
OldStat[i] = S[i]; OldStat[i] = LinkStatus[i];
} }
/* Reset pump energy usage */ /* Reset pump energy usage */
@@ -205,7 +205,7 @@ int runhyd(long *t)
if (Statflag) writehydstat(iter,relerr); if (Statflag) writehydstat(iter,relerr);
/* solution info */ /* solution info */
_relativeError = (int)relerr; _relativeError = relerr;
_iterations = iter; _iterations = iter;
/*** Updated 3/1/01 ***/ /*** Updated 3/1/01 ***/
@@ -375,7 +375,7 @@ void setlinkflow(int k, double dh)
/* use approx. inverse of formula. */ /* use approx. inverse of formula. */
if (Formflag == DW) if (Formflag == DW)
{ {
x = -log(K[k]/3.7/Link[k].Diam); x = -log(LinkSetting[k]/3.7/Link[k].Diam);
y = sqrt(ABS(dh)/Link[k].R/1.32547); y = sqrt(ABS(dh)/Link[k].R/1.32547);
Q[k] = x*y; Q[k] = x*y;
} }
@@ -402,17 +402,17 @@ void setlinkflow(int k, double dh)
/* For custom pump curve, interpolate from curve */ /* For custom pump curve, interpolate from curve */
if (Pump[p].Ptype == CUSTOM) if (Pump[p].Ptype == CUSTOM)
{ {
dh = -dh*Ucf[HEAD]/SQR(K[k]); dh = -dh*Ucf[HEAD]/SQR(LinkSetting[k]);
i = Pump[p].Hcurve; i = Pump[p].Hcurve;
Q[k] = interp(Curve[i].Npts,Curve[i].Y,Curve[i].X, Q[k] = interp(Curve[i].Npts,Curve[i].Y,Curve[i].X,
dh)*K[k]/Ucf[FLOW]; dh)*LinkSetting[k]/Ucf[FLOW];
} }
/* Otherwise use inverse of power curve */ /* Otherwise use inverse of power curve */
else else
{ {
h0 = -SQR(K[k])*Pump[p].H0; h0 = -SQR(LinkSetting[k])*Pump[p].H0;
x = pow(K[k],2.0-Pump[p].N); x = pow(LinkSetting[k],2.0-Pump[p].N);
x = ABS(h0-dh)/(Pump[p].R*x), x = ABS(h0-dh)/(Pump[p].R*x),
y = 1.0/Pump[p].N; y = 1.0/Pump[p].N;
Q[k] = pow(x,y); Q[k] = pow(x,y);
@@ -606,7 +606,7 @@ void demands()
if (djunc > 0.0) Dsystem += djunc; if (djunc > 0.0) Dsystem += djunc;
sum += djunc; sum += djunc;
} }
D[i] = sum; NodeDemand[i] = sum;
} }
/* Update head at fixed grade nodes with time patterns. */ /* Update head at fixed grade nodes with time patterns. */
@@ -619,7 +619,7 @@ void demands()
{ {
k = p % (long) Pattern[j].Length; k = p % (long) Pattern[j].Length;
i = Tank[n].Node; i = Tank[n].Node;
H[i] = Node[i].El*Pattern[j].F[k]; NodeHead[i] = Node[i].El*Pattern[j].F[k];
} }
} }
} }
@@ -632,7 +632,7 @@ void demands()
{ {
i = Pump[n].Link; i = Pump[n].Link;
k = p % (long) Pattern[j].Length; k = p % (long) Pattern[j].Length;
setlinksetting(i, Pattern[j].F[k], &S[i], &K[i]); setlinksetting(i, Pattern[j].F[k], &LinkStatus[i], &LinkSetting[i]);
} }
} }
} /* End of demands */ } /* End of demands */
@@ -664,8 +664,8 @@ int controls()
/* Link is controlled by tank level */ /* Link is controlled by tank level */
if ((n = Control[i].Node) > 0 && n > Njuncs) if ((n = Control[i].Node) > 0 && n > Njuncs)
{ {
h = H[n]; h = NodeHead[n];
vplus = ABS(D[n]); vplus = ABS(NodeDemand[n]);
v1 = tankvolume(n-Njuncs,h); v1 = tankvolume(n-Njuncs,h);
v2 = tankvolume(n-Njuncs,Control[i].Grade); v2 = tankvolume(n-Njuncs,Control[i].Grade);
if (Control[i].Type == LOWLEVEL && v1 <= v2 + vplus) if (Control[i].Type == LOWLEVEL && v1 <= v2 + vplus)
@@ -689,16 +689,16 @@ int controls()
/* Update link status & pump speed or valve setting */ /* Update link status & pump speed or valve setting */
if (reset == 1) if (reset == 1)
{ {
if (S[k] <= CLOSED) s1 = CLOSED; if (LinkStatus[k] <= CLOSED) s1 = CLOSED;
else s1 = OPEN; else s1 = OPEN;
s2 = Control[i].Status; s2 = Control[i].Status;
k1 = K[k]; k1 = LinkSetting[k];
k2 = k1; k2 = k1;
if (Link[k].Type > PIPE) k2 = Control[i].Setting; if (Link[k].Type > PIPE) k2 = Control[i].Setting;
if (s1 != s2 || k1 != k2) if (s1 != s2 || k1 != k2)
{ {
S[k] = s2; LinkStatus[k] = s2;
K[k] = k2; LinkSetting[k] = k2;
if (Statflag) writecontrolaction(k,i); if (Statflag) writecontrolaction(k,i);
// if (s1 != s2) initlinkflow(k, S[k], K[k]); // if (s1 != s2) initlinkflow(k, S[k], K[k]);
setsum++; setsum++;
@@ -764,8 +764,8 @@ void tanktimestep(long *tstep)
{ {
if (Tank[i].A == 0.0) continue; /* Skip reservoirs */ if (Tank[i].A == 0.0) continue; /* Skip reservoirs */
n = Tank[i].Node; n = Tank[i].Node;
h = H[n]; /* Current tank grade */ h = NodeHead[n]; /* Current tank grade */
q = D[n]; /* Flow into tank */ q = NodeDemand[n]; /* Flow into tank */
if (ABS(q) <= QZERO) continue; if (ABS(q) <= QZERO) continue;
if (q > 0.0 && h < Tank[i].Hmax) if (q > 0.0 && h < Tank[i].Hmax)
{ {
@@ -802,8 +802,8 @@ void controltimestep(long *tstep)
if ( (n = Control[i].Node) > 0) /* Node control: */ if ( (n = Control[i].Node) > 0) /* Node control: */
{ {
if ((j = n-Njuncs) <= 0) continue; /* Node is a tank */ if ((j = n-Njuncs) <= 0) continue; /* Node is a tank */
h = H[n]; /* Current tank grade */ h = NodeHead[n]; /* Current tank grade */
q = D[n]; /* Flow into tank */ q = NodeDemand[n]; /* Flow into tank */
if (ABS(q) <= QZERO) continue; if (ABS(q) <= QZERO) continue;
if if
( (h < Control[i].Grade && ( (h < Control[i].Grade &&
@@ -838,8 +838,8 @@ void controltimestep(long *tstep)
/* Check if rule actually changes link status or setting */ /* Check if rule actually changes link status or setting */
k = Control[i].Link; k = Control[i].Link;
if ( if (
(Link[k].Type > PIPE && K[k] != Control[i].Setting) || (Link[k].Type > PIPE && LinkSetting[k] != Control[i].Setting) ||
(S[k] != Control[i].Status) (LinkStatus[k] != Control[i].Status)
) )
*tstep = t; *tstep = t;
} }
@@ -954,7 +954,7 @@ void addenergy(long hstep)
{ {
/* Skip closed pumps */ /* Skip closed pumps */
k = Pump[j].Link; k = Pump[j].Link;
if (S[k] <= CLOSED) continue; if (LinkStatus[k] <= CLOSED) continue;
q = MAX(QZERO, ABS(Q[k])); q = MAX(QZERO, ABS(Q[k]));
/* Find pump-specific energy cost */ /* Find pump-specific energy cost */
@@ -1001,7 +1001,7 @@ void getenergy(int k, double *kw, double *eff)
/*** Updated 6/24/02 ***/ /*** Updated 6/24/02 ***/
/* No energy if link is closed */ /* No energy if link is closed */
if (S[k] <= CLOSED) if (LinkStatus[k] <= CLOSED)
{ {
*kw = 0.0; *kw = 0.0;
*eff = 0.0; *eff = 0.0;
@@ -1011,7 +1011,7 @@ void getenergy(int k, double *kw, double *eff)
/* Determine flow and head difference */ /* Determine flow and head difference */
q = ABS(Q[k]); q = ABS(Q[k]);
dh = ABS(H[Link[k].N1] - H[Link[k].N2]); dh = ABS(NodeHead[Link[k].N1] - NodeHead[Link[k].N2]);
/* For pumps, find effic. at current flow */ /* For pumps, find effic. at current flow */
if (Link[k].Type == PUMP) if (Link[k].Type == PUMP)
@@ -1053,18 +1053,18 @@ void tanklevels(long tstep)
/* Update the tank's volume & water elevation */ /* Update the tank's volume & water elevation */
n = Tank[i].Node; n = Tank[i].Node;
dv = D[n]*tstep; dv = NodeDemand[n]*tstep;
Tank[i].V += dv; Tank[i].V += dv;
/*** Updated 6/24/02 ***/ /*** Updated 6/24/02 ***/
/* Check if tank full/empty within next second */ /* Check if tank full/empty within next second */
if (Tank[i].V + D[n] >= Tank[i].Vmax) { if (Tank[i].V + NodeDemand[n] >= Tank[i].Vmax) {
Tank[i].V = Tank[i].Vmax; Tank[i].V = Tank[i].Vmax;
} }
else if (Tank[i].V - D[n] <= Tank[i].Vmin) { else if (Tank[i].V - NodeDemand[n] <= Tank[i].Vmin) {
Tank[i].V = Tank[i].Vmin; Tank[i].V = Tank[i].Vmin;
} }
H[n] = tankgrade(i,Tank[i].V); NodeHead[n] = tankgrade(i,Tank[i].V);
} }
} /* End of tanklevels */ } /* End of tanklevels */
@@ -1188,7 +1188,7 @@ int netsolve(int *iter, double *relerr)
/* Update current solution. */ /* Update current solution. */
/* (Row[i] = row of solution matrix corresponding to node i). */ /* (Row[i] = row of solution matrix corresponding to node i). */
for (i=1; i<=Njuncs; i++) H[i] = F[Row[i]]; /* Update heads */ for (i=1; i<=Njuncs; i++) NodeHead[i] = F[Row[i]]; /* Update heads */
newerr = newflows(); /* Update flows */ newerr = newflows(); /* Update flows */
*relerr = newerr; *relerr = newerr;
@@ -1244,7 +1244,7 @@ int netsolve(int *iter, double *relerr)
} }
/* Add any emitter flows to junction demands */ /* Add any emitter flows to junction demands */
for (i=1; i<=Njuncs; i++) D[i] += E[i]; for (i=1; i<=Njuncs; i++) NodeDemand[i] += E[i];
return(errcode); return(errcode);
} /* End of netsolve */ } /* End of netsolve */
@@ -1274,15 +1274,15 @@ int badvalve(int n)
Link[k].Type == PSV || Link[k].Type == PSV ||
Link[k].Type == FCV) Link[k].Type == FCV)
{ {
if (S[k] == ACTIVE) if (LinkStatus[k] == ACTIVE)
{ {
if (Statflag == FULL) if (Statflag == FULL)
{ {
sprintf(Msg,FMT61,clocktime(Atime,Htime),Link[k].ID); sprintf(Msg,FMT61,clocktime(Atime,Htime),Link[k].ID);
writeline(Msg); writeline(Msg);
} }
if (Link[k].Type == FCV) S[k] = XFCV; if (Link[k].Type == FCV) LinkStatus[k] = XFCV;
else S[k] = XPRESSURE; else LinkStatus[k] = XPRESSURE;
return(1); return(1);
} }
} }
@@ -1313,25 +1313,25 @@ int valvestatus()
for (i=1; i<=Nvalves; i++) /* Examine each valve */ for (i=1; i<=Nvalves; i++) /* Examine each valve */
{ {
k = Valve[i].Link; /* Link index of valve */ k = Valve[i].Link; /* Link index of valve */
if (K[k] == MISSING) continue; /* Valve status fixed */ if (LinkSetting[k] == MISSING) continue; /* Valve status fixed */
n1 = Link[k].N1; /* Start & end nodes */ n1 = Link[k].N1; /* Start & end nodes */
n2 = Link[k].N2; n2 = Link[k].N2;
s = S[k]; /* Save current status */ s = LinkStatus[k]; /* Save current status */
// if (s != CLOSED /* No change if flow is */ //(2.00.11 - LR) // if (s != CLOSED /* No change if flow is */ //(2.00.11 - LR)
// && ABS(Q[k]) < Qtol) continue; /* negligible. */ //(2.00.11 - LR) // && ABS(Q[k]) < Qtol) continue; /* negligible. */ //(2.00.11 - LR)
switch (Link[k].Type) /* Evaluate new status: */ switch (Link[k].Type) /* Evaluate new status: */
{ {
case PRV: hset = Node[n2].El + K[k]; case PRV: hset = Node[n2].El + LinkSetting[k];
S[k] = prvstatus(k,s,hset,H[n1],H[n2]); LinkStatus[k] = prvstatus(k,s,hset,NodeHead[n1],NodeHead[n2]);
break; break;
case PSV: hset = Node[n1].El + K[k]; case PSV: hset = Node[n1].El + LinkSetting[k];
S[k] = psvstatus(k,s,hset,H[n1],H[n2]); LinkStatus[k] = psvstatus(k,s,hset,NodeHead[n1],NodeHead[n2]);
break; break;
//// FCV status checks moved back into the linkstatus() function //// //(2.00.12 - LR) //// FCV status checks moved back into the linkstatus() function //// //(2.00.12 - LR)
// case FCV: S[k] = fcvstatus(k,s,H[n1],H[n2]); //(2.00.12 - LR) // case FCV: S[k] = fcvstatus(k,s,NodeHead[n1],NodeHead[n2]); //(2.00.12 - LR)
// break; //(2.00.12 - LR) // break; //(2.00.12 - LR)
default: continue; default: continue;
@@ -1342,9 +1342,9 @@ int valvestatus()
/* This strategy improves convergence. */ /* This strategy improves convergence. */
/* Check for status change */ /* Check for status change */
if (s != S[k]) if (s != LinkStatus[k])
{ {
if (Statflag == FULL) writestatchange(k,s,S[k]); if (Statflag == FULL) writestatchange(k,s,LinkStatus[k]);
change = TRUE; change = TRUE;
} }
} }
@@ -1375,29 +1375,29 @@ int linkstatus()
{ {
n1 = Link[k].N1; n1 = Link[k].N1;
n2 = Link[k].N2; n2 = Link[k].N2;
dh = H[n1] - H[n2]; dh = NodeHead[n1] - NodeHead[n2];
/* Re-open temporarily closed links (status = XHEAD or TEMPCLOSED) */ /* Re-open temporarily closed links (status = XHEAD or TEMPCLOSED) */
status = S[k]; status = LinkStatus[k];
if (status == XHEAD || status == TEMPCLOSED) S[k] = OPEN; if (status == XHEAD || status == TEMPCLOSED) LinkStatus[k] = OPEN;
/* Check for status changes in CVs and pumps */ /* Check for status changes in CVs and pumps */
if (Link[k].Type == CV) S[k] = cvstatus(S[k],dh,Q[k]); if (Link[k].Type == CV) LinkStatus[k] = cvstatus(LinkStatus[k],dh,Q[k]);
if (Link[k].Type == PUMP && S[k] >= OPEN && K[k] > 0.0) //(2.00.11 - LR) if (Link[k].Type == PUMP && LinkStatus[k] >= OPEN && LinkSetting[k] > 0.0) //(2.00.11 - LR)
S[k] = pumpstatus(k,-dh); LinkStatus[k] = pumpstatus(k,-dh);
/* Check for status changes in non-fixed FCVs */ /* Check for status changes in non-fixed FCVs */
if (Link[k].Type == FCV && K[k] != MISSING) //(2.00.12 - LR)// if (Link[k].Type == FCV && LinkSetting[k] != MISSING) //(2.00.12 - LR)//
S[k] = fcvstatus(k,status,H[n1],H[n2]); //(2.00.12 - LR)// LinkStatus[k] = fcvstatus(k,status,NodeHead[n1],NodeHead[n2]); //(2.00.12 - LR)//
/* Check for flow into (out of) full (empty) tanks */ /* Check for flow into (out of) full (empty) tanks */
if (n1 > Njuncs || n2 > Njuncs) tankstatus(k,n1,n2); if (n1 > Njuncs || n2 > Njuncs) tankstatus(k,n1,n2);
/* Note change in link status; do not revise link flow */ //(2.00.11 - LR) /* Note change in link status; do not revise link flow */ //(2.00.11 - LR)
if (status != S[k]) if (status != LinkStatus[k])
{ {
change = TRUE; change = TRUE;
if (Statflag == FULL) writestatchange(k,status,S[k]); if (Statflag == FULL) writestatchange(k,status,LinkStatus[k]);
//if (S[k] <= CLOSED) Q[k] = QZERO; //(2.00.11 - LR) //if (S[k] <= CLOSED) Q[k] = QZERO; //(2.00.11 - LR)
//else setlinkflow(k, dh); //(2.00.11 - LR) //else setlinkflow(k, dh); //(2.00.11 - LR)
@@ -1449,7 +1449,7 @@ char pumpstatus(int k, double dh)
/* Prevent reverse flow through pump */ /* Prevent reverse flow through pump */
p = PUMPINDEX(k); p = PUMPINDEX(k);
if (Pump[p].Ptype == CONST_HP) hmax = BIG; if (Pump[p].Ptype == CONST_HP) hmax = BIG;
else hmax = SQR(K[k])*Pump[p].Hmax; else hmax = SQR(LinkSetting[k])*Pump[p].Hmax;
if (dh > hmax + Htol) return(XHEAD); if (dh > hmax + Htol) return(XHEAD);
/*** Flow higher than pump curve no longer results in a status change ***/ //(2.00.11 - LR) /*** Flow higher than pump curve no longer results in a status change ***/ //(2.00.11 - LR)
@@ -1477,7 +1477,7 @@ char prvstatus(int k, char s, double hset, double h1, double h2)
double htol = Htol; double htol = Htol;
status = s; status = s;
if (K[k] == MISSING) return(status); /* Status fixed by user */ if (LinkSetting[k] == MISSING) return(status); /* Status fixed by user */
hml = Link[k].Km*SQR(Q[k]); /* Head loss when open */ hml = Link[k].Km*SQR(Q[k]); /* Head loss when open */
/*** Status rules below have changed. ***/ //(2.00.11 - LR) /*** Status rules below have changed. ***/ //(2.00.11 - LR)
@@ -1527,7 +1527,7 @@ char psvstatus(int k, char s, double hset, double h1, double h2)
double htol = Htol; double htol = Htol;
status = s; status = s;
if (K[k] == MISSING) return(status); /* Status fixed by user */ if (LinkSetting[k] == MISSING) return(status); /* Status fixed by user */
hml = Link[k].Km*SQR(Q[k]); /* Head loss when open */ hml = Link[k].Km*SQR(Q[k]); /* Head loss when open */
/*** Status rules below have changed. ***/ //(2.00.11 - LR) /*** Status rules below have changed. ***/ //(2.00.11 - LR)
@@ -1580,9 +1580,15 @@ char fcvstatus(int k, char s, double h1, double h2)
{ {
char status; /* New valve status */ char status; /* New valve status */
status = s; status = s;
if (h1 - h2 < -Htol) status = XFCV; if (h1 - h2 < -Htol) {
else if ( Q[k] < -Qtol ) status = XFCV; //(2.00.11 - LR) status = XFCV;
else if (s == XFCV && Q[k] >= K[k]) status = ACTIVE; }
else if ( Q[k] < -Qtol ) {
status = XFCV; //(2.00.11 - LR)
}
else if (s == XFCV && Q[k] >= LinkSetting[k]) {
status = ACTIVE;
}
return(status); return(status);
} }
@@ -1615,39 +1621,39 @@ void tankstatus(int k, int n1, int n2)
n2 = n; n2 = n;
q = -q; q = -q;
} }
h = H[n1] - H[n2]; h = NodeHead[n1] - NodeHead[n2];
/* Skip reservoirs & closed links */ /* Skip reservoirs & closed links */
if (Tank[i].A == 0.0 || S[k] <= CLOSED) return; if (Tank[i].A == 0.0 || LinkStatus[k] <= CLOSED) return;
/* If tank full, then prevent flow into it */ /* If tank full, then prevent flow into it */
if (H[n1] >= Tank[i].Hmax - Htol) if (NodeHead[n1] >= Tank[i].Hmax - Htol)
{ {
/* Case 1: Link is a pump discharging into tank */ /* Case 1: Link is a pump discharging into tank */
if ( Link[k].Type == PUMP ) if ( Link[k].Type == PUMP )
{ {
if (Link[k].N2 == n1) S[k] = TEMPCLOSED; if (Link[k].N2 == n1) LinkStatus[k] = TEMPCLOSED;
} }
/* Case 2: Downstream head > tank head */ /* Case 2: Downstream head > tank head */
/* (i.e., an open outflow check valve would close) */ /* (i.e., an open outflow check valve would close) */
else if (cvstatus(OPEN, h, q) == CLOSED) S[k] = TEMPCLOSED; else if (cvstatus(OPEN, h, q) == CLOSED) LinkStatus[k] = TEMPCLOSED;
} }
/* If tank empty, then prevent flow out of it */ /* If tank empty, then prevent flow out of it */
if (H[n1] <= Tank[i].Hmin + Htol) if (NodeHead[n1] <= Tank[i].Hmin + Htol)
{ {
/* Case 1: Link is a pump discharging from tank */ /* Case 1: Link is a pump discharging from tank */
if ( Link[k].Type == PUMP) if ( Link[k].Type == PUMP)
{ {
if (Link[k].N1 == n1) S[k] = TEMPCLOSED; if (Link[k].N1 == n1) LinkStatus[k] = TEMPCLOSED;
} }
/* Case 2: Tank head > downstream head */ /* Case 2: Tank head > downstream head */
/* (i.e., a closed outflow check valve would open) */ /* (i.e., a closed outflow check valve would open) */
else if (cvstatus(CLOSED, h, q) == OPEN) S[k] = TEMPCLOSED; else if (cvstatus(CLOSED, h, q) == OPEN) LinkStatus[k] = TEMPCLOSED;
} }
} /* End of tankstatus */ } /* End of tankstatus */
@@ -1681,10 +1687,10 @@ int pswitch()
{ {
/* Determine if control conditions are satisfied */ /* Determine if control conditions are satisfied */
if (Control[i].Type == LOWLEVEL if (Control[i].Type == LOWLEVEL
&& H[n] <= Control[i].Grade + Htol ) && NodeHead[n] <= Control[i].Grade + Htol )
reset = 1; reset = 1;
if (Control[i].Type == HILEVEL if (Control[i].Type == HILEVEL
&& H[n] >= Control[i].Grade - Htol ) && NodeHead[n] >= Control[i].Grade - Htol )
reset = 1; reset = 1;
} }
@@ -1692,28 +1698,28 @@ int pswitch()
if (reset == 1) if (reset == 1)
{ {
change = 0; change = 0;
s = S[k]; s = LinkStatus[k];
if (Link[k].Type == PIPE) if (Link[k].Type == PIPE)
{ {
if (s != Control[i].Status) change = 1; if (s != Control[i].Status) change = 1;
} }
if (Link[k].Type == PUMP) if (Link[k].Type == PUMP)
{ {
if (K[k] != Control[i].Setting) change = 1; if (LinkSetting[k] != Control[i].Setting) change = 1;
} }
if (Link[k].Type >= PRV) if (Link[k].Type >= PRV)
{ {
if (K[k] != Control[i].Setting) change = 1; if (LinkSetting[k] != Control[i].Setting) change = 1;
else if (K[k] == MISSING && else if (LinkSetting[k] == MISSING &&
s != Control[i].Status) change = 1; s != Control[i].Status) change = 1;
} }
/* If a change occurs, update status & setting */ /* If a change occurs, update status & setting */
if (change) if (change)
{ {
S[k] = Control[i].Status; LinkStatus[k] = Control[i].Status;
if (Link[k].Type > PIPE) K[k] = Control[i].Setting; if (Link[k].Type > PIPE) LinkSetting[k] = Control[i].Setting;
if (Statflag == FULL) writestatchange(k,s,S[k]); if (Statflag == FULL) writestatchange(k,s,LinkStatus[k]);
/* Re-set flow if status has changed */ /* Re-set flow if status has changed */
// if (S[k] != s) initlinkflow(k, S[k], K[k]); // if (S[k] != s) initlinkflow(k, S[k], K[k]);
@@ -1741,7 +1747,7 @@ double newflows()
int k, n, n1, n2; int k, n, n1, n2;
/* Initialize net inflows (i.e., demands) at tanks */ /* Initialize net inflows (i.e., demands) at tanks */
for (n=Njuncs+1; n <= Nnodes; n++) D[n] = 0.0; for (n=Njuncs+1; n <= Nnodes; n++) NodeDemand[n] = 0.0;
/* Initialize sum of flows & corrections */ /* Initialize sum of flows & corrections */
qsum = 0.0; qsum = 0.0;
@@ -1761,7 +1767,7 @@ double newflows()
n1 = Link[k].N1; n1 = Link[k].N1;
n2 = Link[k].N2; n2 = Link[k].N2;
dh = H[n1] - H[n2]; dh = NodeHead[n1] - NodeHead[n2];
dq = Y[k] - P[k]*dh; dq = Y[k] - P[k]*dh;
/* Adjust flow change by the relaxation factor */ //(2.00.11 - LR) /* Adjust flow change by the relaxation factor */ //(2.00.11 - LR)
@@ -1780,10 +1786,10 @@ double newflows()
dqsum += ABS(dq); dqsum += ABS(dq);
/* Update net flows to tanks */ /* Update net flows to tanks */
if ( S[k] > CLOSED ) //(2.00.12 - LR) if ( LinkStatus[k] > CLOSED ) //(2.00.12 - LR)
{ {
if (n1 > Njuncs) D[n1] -= Q[k]; if (n1 > Njuncs) NodeDemand[n1] -= Q[k];
if (n2 > Njuncs) D[n2] += Q[k]; if (n2 > Njuncs) NodeDemand[n2] += Q[k];
} }
} }
@@ -1861,7 +1867,7 @@ void linkcoeffs()
case PRV: case PRV:
case PSV: /* If valve status fixed then treat as pipe */ case PSV: /* If valve status fixed then treat as pipe */
/* otherwise ignore the valve for now. */ /* otherwise ignore the valve for now. */
if (K[k] == MISSING) valvecoeff(k); //pipecoeff(k); //(2.00.11 - LR) if (LinkSetting[k] == MISSING) valvecoeff(k); //pipecoeff(k); //(2.00.11 - LR)
else continue; else continue;
break; break;
default: continue; default: continue;
@@ -1877,13 +1883,13 @@ void linkcoeffs()
Aii[Row[n1]] += P[k]; /* Diagonal coeff. */ Aii[Row[n1]] += P[k]; /* Diagonal coeff. */
F[Row[n1]] += Y[k]; /* RHS coeff. */ F[Row[n1]] += Y[k]; /* RHS coeff. */
} }
else F[Row[n2]] += (P[k]*H[n1]); /* Node n1 is a tank */ else F[Row[n2]] += (P[k]*NodeHead[n1]); /* Node n1 is a tank */
if (n2 <= Njuncs) /* Node n2 is junction */ if (n2 <= Njuncs) /* Node n2 is junction */
{ {
Aii[Row[n2]] += P[k]; /* Diagonal coeff. */ Aii[Row[n2]] += P[k]; /* Diagonal coeff. */
F[Row[n2]] -= Y[k]; /* RHS coeff. */ F[Row[n2]] -= Y[k]; /* RHS coeff. */
} }
else F[Row[n1]] += (P[k]*H[n2]); /* Node n2 is a tank */ else F[Row[n1]] += (P[k]*NodeHead[n2]); /* Node n2 is a tank */
} }
} /* End of linkcoeffs */ } /* End of linkcoeffs */
@@ -1904,7 +1910,7 @@ void nodecoeffs()
/* flow imbalance & add imbalance to RHS array F. */ /* flow imbalance & add imbalance to RHS array F. */
for (i=1; i<=Njuncs; i++) for (i=1; i<=Njuncs; i++)
{ {
X[i] -= D[i]; X[i] -= NodeDemand[i];
F[Row[i]] += X[i]; F[Row[i]] += X[i];
} }
} /* End of nodecoeffs */ } /* End of nodecoeffs */
@@ -1925,7 +1931,7 @@ void valvecoeffs()
for (i=1; i<=Nvalves; i++) /* Examine each valve */ for (i=1; i<=Nvalves; i++) /* Examine each valve */
{ {
k = Valve[i].Link; /* Link index of valve */ k = Valve[i].Link; /* Link index of valve */
if (K[k] == MISSING) continue; /* Valve status fixed */ if (LinkSetting[k] == MISSING) continue; /* Valve status fixed */
n1 = Link[k].N1; /* Start & end nodes */ n1 = Link[k].N1; /* Start & end nodes */
n2 = Link[k].N2; n2 = Link[k].N2;
switch (Link[k].Type) /* Call valve-specific */ switch (Link[k].Type) /* Call valve-specific */
@@ -1992,7 +1998,7 @@ double emitflowchange(int i)
p = 1/RQtol; p = 1/RQtol;
else else
p = 1.0/p; p = 1.0/p;
return(E[i]/Qexp - p*(H[i] - Node[i].El)); return(E[i]/Qexp - p*(NodeHead[i] - Node[i].El));
} }
@@ -2019,7 +2025,7 @@ void pipecoeff(int k)
dfdq; /* Derivative of fric. fact. */ dfdq; /* Derivative of fric. fact. */
/* For closed pipe use headloss formula: h = CBIG*q */ /* For closed pipe use headloss formula: h = CBIG*q */
if (S[k] <= CLOSED) if (LinkStatus[k] <= CLOSED)
{ {
P[k] = 1.0/CBIG; P[k] = 1.0/CBIG;
Y[k] = Q[k]; Y[k] = Q[k];
@@ -2148,8 +2154,10 @@ void pumpcoeff(int k)
r, /* Flow resistance coeff. */ r, /* Flow resistance coeff. */
n; /* Flow exponent coeff. */ n; /* Flow exponent coeff. */
double setting = LinkSetting[k];
/* Use high resistance pipe if pump closed or cannot deliver head */ /* Use high resistance pipe if pump closed or cannot deliver head */
if (S[k] <= CLOSED || K[k] == 0.0) if (LinkStatus[k] <= CLOSED || setting == 0.0)
{ {
//pipecoeff(k); //(2.00.11 - LR) //pipecoeff(k); //(2.00.11 - LR)
P[k] = 1.0/CBIG; //(2.00.11 - LR) P[k] = 1.0/CBIG; //(2.00.11 - LR)
@@ -2166,7 +2174,7 @@ void pumpcoeff(int k)
{ {
/* Find intercept (h0) & slope (r) of pump curve */ /* Find intercept (h0) & slope (r) of pump curve */
/* line segment which contains speed-adjusted flow. */ /* line segment which contains speed-adjusted flow. */
curvecoeff(Pump[p].Hcurve,q/K[k],&h0,&r); curvecoeff(Pump[p].Hcurve, q/setting, &h0, &r);
/* Determine head loss coefficients. */ /* Determine head loss coefficients. */
Pump[p].H0 = -h0; Pump[p].H0 = -h0;
@@ -2175,9 +2183,9 @@ void pumpcoeff(int k)
} }
/* Adjust head loss coefficients for pump speed. */ /* Adjust head loss coefficients for pump speed. */
h0 = SQR(K[k])*Pump[p].H0; h0 = SQR(setting)*Pump[p].H0;
n = Pump[p].N; n = Pump[p].N;
r = Pump[p].R*pow(K[k],2.0-n); r = Pump[p].R*pow(setting,2.0-n);
if (n != 1.0) r = n*r*pow(q,n-1.0); if (n != 1.0) r = n*r*pow(q,n-1.0);
/* Compute inverse headloss gradient (P) and flow correction factor (Y) */ /* Compute inverse headloss gradient (P) and flow correction factor (Y) */
@@ -2241,7 +2249,7 @@ void gpvcoeff(int k)
/*** Updated 9/7/00 ***/ /*** Updated 9/7/00 ***/
/* Treat as a pipe if valve closed */ /* Treat as a pipe if valve closed */
if (S[k] == CLOSED) valvecoeff(k); //pipecoeff(k); //(2.00.11 - LR) if (LinkStatus[k] == CLOSED) valvecoeff(k); //pipecoeff(k); //(2.00.11 - LR)
/* Otherwise utilize headloss curve */ /* Otherwise utilize headloss curve */
/* whose index is stored in K */ /* whose index is stored in K */
@@ -2253,7 +2261,7 @@ void gpvcoeff(int k)
/*** Updated 10/25/00 ***/ /*** Updated 10/25/00 ***/
/*** Updated 12/29/00 ***/ /*** Updated 12/29/00 ***/
curvecoeff((int)ROUND(K[k]),q,&h0,&r); curvecoeff((int)ROUND(LinkSetting[k]),q,&h0,&r);
/* Compute inverse headloss gradient (P) */ /* Compute inverse headloss gradient (P) */
/* and flow correction factor (Y). */ /* and flow correction factor (Y). */
@@ -2273,19 +2281,19 @@ void pbvcoeff(int k)
*/ */
{ {
/* If valve fixed OPEN or CLOSED then treat as a pipe */ /* If valve fixed OPEN or CLOSED then treat as a pipe */
if (K[k] == MISSING || K[k] == 0.0) valvecoeff(k); //pipecoeff(k); //(2.00.11 - LR) if (LinkSetting[k] == MISSING || LinkSetting[k] == 0.0) valvecoeff(k); //pipecoeff(k); //(2.00.11 - LR)
/* If valve is active */ /* If valve is active */
else else
{ {
/* Treat as a pipe if minor loss > valve setting */ /* Treat as a pipe if minor loss > valve setting */
if (Link[k].Km*SQR(Q[k]) > K[k]) valvecoeff(k); //pipecoeff(k); //(2.00.11 - LR) if (Link[k].Km*SQR(Q[k]) > LinkSetting[k]) valvecoeff(k); //pipecoeff(k); //(2.00.11 - LR)
/* Otherwise force headloss across valve to be equal to setting */ /* Otherwise force headloss across valve to be equal to setting */
else else
{ {
P[k] = CBIG; P[k] = CBIG;
Y[k] = K[k]*CBIG; Y[k] = LinkSetting[k]*CBIG;
} }
} }
} /* End of pbvcoeff */ } /* End of pbvcoeff */
@@ -2306,8 +2314,8 @@ void tcvcoeff(int k)
km = Link[k].Km; km = Link[k].Km;
/* If valve not fixed OPEN or CLOSED, compute its loss coeff. */ /* If valve not fixed OPEN or CLOSED, compute its loss coeff. */
if (K[k] != MISSING) if (LinkSetting[k] != MISSING)
Link[k].Km = 0.02517*K[k]/(SQR(Link[k].Diam)*SQR(Link[k].Diam)); Link[k].Km = 0.02517*LinkSetting[k]/(SQR(Link[k].Diam)*SQR(Link[k].Diam));
/* Then apply usual pipe formulas */ /* Then apply usual pipe formulas */
valvecoeff(k); //pipecoeff(k); //(2.00.11 - LR) valvecoeff(k); //pipecoeff(k); //(2.00.11 - LR)
@@ -2333,9 +2341,9 @@ void prvcoeff(int k, int n1, int n2)
double hset; /* Valve head setting */ double hset; /* Valve head setting */
i = Row[n1]; /* Matrix rows of nodes */ i = Row[n1]; /* Matrix rows of nodes */
j = Row[n2]; j = Row[n2];
hset = Node[n2].El + K[k]; /* Valve setting */ hset = Node[n2].El + LinkSetting[k]; /* Valve setting */
if (S[k] == ACTIVE) if (LinkStatus[k] == ACTIVE)
{ {
/* /*
Set coeffs. to force head at downstream Set coeffs. to force head at downstream
@@ -2379,9 +2387,9 @@ void psvcoeff(int k, int n1, int n2)
double hset; /* Valve head setting */ double hset; /* Valve head setting */
i = Row[n1]; /* Matrix rows of nodes */ i = Row[n1]; /* Matrix rows of nodes */
j = Row[n2]; j = Row[n2];
hset = Node[n1].El + K[k]; /* Valve setting */ hset = Node[n1].El + LinkSetting[k]; /* Valve setting */
if (S[k] == ACTIVE) if (LinkStatus[k] == ACTIVE)
{ {
/* /*
Set coeffs. to force head at upstream Set coeffs. to force head at upstream
@@ -2423,7 +2431,7 @@ void fcvcoeff(int k, int n1, int n2)
{ {
int i,j; /* Rows in solution matrix */ int i,j; /* Rows in solution matrix */
double q; /* Valve flow setting */ double q; /* Valve flow setting */
q = K[k]; q = LinkSetting[k];
i = Row[n1]; i = Row[n1];
j = Row[n2]; j = Row[n2];
@@ -2432,7 +2440,7 @@ void fcvcoeff(int k, int n1, int n2)
flow setting as external demand at upstream node flow setting as external demand at upstream node
and external supply at downstream node. and external supply at downstream node.
*/ */
if (S[k] == ACTIVE) if (LinkStatus[k] == ACTIVE)
{ {
X[n1] -= q; X[n1] -= q;
F[i] -= q; F[i] -= q;
@@ -2474,7 +2482,7 @@ void valvecoeff(int k)
double p; double p;
// Valve is closed. Use a very small matrix coeff. // Valve is closed. Use a very small matrix coeff.
if (S[k] <= CLOSED) if (LinkStatus[k] <= CLOSED)
{ {
P[k] = 1.0/CBIG; P[k] = 1.0/CBIG;
Y[k] = Q[k]; Y[k] = Q[k];

View File

@@ -99,9 +99,9 @@ int juncdata()
demand->Pat = p; demand->Pat = p;
demand->next = Node[Njuncs].D; demand->next = Node[Njuncs].D;
Node[Njuncs].D = demand; Node[Njuncs].D = demand;
D[Njuncs] = y; NodeDemand[Njuncs] = y;
} }
else D[Njuncs] = MISSING; else NodeDemand[Njuncs] = MISSING;
/*** end of update ***/ /*** end of update ***/
return(0); return(0);
} /* end of juncdata */ } /* end of juncdata */
@@ -682,11 +682,11 @@ int demanddata()
/*** Updated 6/24/02 ***/ /*** Updated 6/24/02 ***/
demand = Node[j].D; demand = Node[j].D;
if (demand && D[j] != MISSING) if (demand && NodeDemand[j] != MISSING)
{ {
demand->Base = y; demand->Base = y;
demand->Pat = p; demand->Pat = p;
D[j] = MISSING; NodeDemand[j] = MISSING;
} }
/*** End of update ***/ /*** End of update ***/

View File

@@ -152,30 +152,30 @@ int savehyd(long *htime)
fwrite(&t,sizeof(INT4),1,HydFile); fwrite(&t,sizeof(INT4),1,HydFile);
/* Save current nodal demands (D) */ /* Save current nodal demands (D) */
for (i=1; i<=Nnodes; i++) x[i] = (REAL4)D[i]; for (i=1; i<=Nnodes; i++) x[i] = (REAL4)NodeDemand[i];
fwrite(x+1,sizeof(REAL4),Nnodes,HydFile); fwrite(x+1,sizeof(REAL4),Nnodes,HydFile);
/* Copy heads (H) to buffer of floats (x) and save buffer */ /* Copy heads (H) to buffer of floats (x) and save buffer */
for (i=1; i<=Nnodes; i++) x[i] = (REAL4)H[i]; for (i=1; i<=Nnodes; i++) x[i] = (REAL4)NodeHead[i];
fwrite(x+1,sizeof(REAL4),Nnodes,HydFile); fwrite(x+1,sizeof(REAL4),Nnodes,HydFile);
/* Force flow in closed links to be zero then save flows */ /* Force flow in closed links to be zero then save flows */
for (i=1; i<=Nlinks; i++) for (i=1; i<=Nlinks; i++)
{ {
if (S[i] <= CLOSED) x[i] = 0.0f; if (LinkStatus[i] <= CLOSED) x[i] = 0.0f;
else x[i] = (REAL4)Q[i]; else x[i] = (REAL4)Q[i];
} }
fwrite(x+1,sizeof(REAL4),Nlinks,HydFile); fwrite(x+1,sizeof(REAL4),Nlinks,HydFile);
/* Copy link status to buffer of floats (x) & write buffer */ /* Copy link status to buffer of floats (x) & write buffer */
for (i=1; i<=Nlinks; i++) x[i] = (REAL4)S[i]; for (i=1; i<=Nlinks; i++) x[i] = (REAL4)LinkStatus[i];
fwrite(x+1,sizeof(REAL4),Nlinks,HydFile); fwrite(x+1,sizeof(REAL4),Nlinks,HydFile);
/* Save link settings & check for successful write-to-disk */ /* Save link settings & check for successful write-to-disk */
/* (We assume that if any of the previous fwrites failed, */ /* (We assume that if any of the previous fwrites failed, */
/* then this one will also fail.) */ /* then this one will also fail.) */
for (i=1; i<=Nlinks; i++) x[i] = (REAL4)K[i]; for (i=1; i<=Nlinks; i++) x[i] = (REAL4)LinkSetting[i];
if (fwrite(x+1,sizeof(REAL4),Nlinks,HydFile) < (unsigned)Nlinks) if (fwrite(x+1,sizeof(REAL4),Nlinks,HydFile) < (unsigned)Nlinks)
errcode = 308; errcode = 308;
free(x); free(x);
@@ -286,19 +286,19 @@ int readhyd(long *hydtime)
*hydtime = t; *hydtime = t;
if (fread(x+1,sizeof(REAL4),Nnodes,HydFile) < (unsigned)Nnodes) result = 0; if (fread(x+1,sizeof(REAL4),Nnodes,HydFile) < (unsigned)Nnodes) result = 0;
else for (i=1; i<=Nnodes; i++) D[i] = x[i]; else for (i=1; i<=Nnodes; i++) NodeDemand[i] = x[i];
if (fread(x+1,sizeof(REAL4),Nnodes,HydFile) < (unsigned)Nnodes) result = 0; if (fread(x+1,sizeof(REAL4),Nnodes,HydFile) < (unsigned)Nnodes) result = 0;
else for (i=1; i<=Nnodes; i++) H[i] = x[i]; else for (i=1; i<=Nnodes; i++) NodeHead[i] = x[i];
if (fread(x+1,sizeof(REAL4),Nlinks,HydFile) < (unsigned)Nlinks) result = 0; if (fread(x+1,sizeof(REAL4),Nlinks,HydFile) < (unsigned)Nlinks) result = 0;
else for (i=1; i<=Nlinks; i++) Q[i] = x[i]; else for (i=1; i<=Nlinks; i++) Q[i] = x[i];
if (fread(x+1,sizeof(REAL4),Nlinks,HydFile) < (unsigned)Nlinks) result = 0; if (fread(x+1,sizeof(REAL4),Nlinks,HydFile) < (unsigned)Nlinks) result = 0;
else for (i=1; i<=Nlinks; i++) S[i] = (char) x[i]; else for (i=1; i<=Nlinks; i++) LinkStatus[i] = (char) x[i];
if (fread(x+1,sizeof(REAL4),Nlinks,HydFile) < (unsigned)Nlinks) result = 0; if (fread(x+1,sizeof(REAL4),Nlinks,HydFile) < (unsigned)Nlinks) result = 0;
else for (i=1; i<=Nlinks; i++) K[i] = x[i]; else for (i=1; i<=Nlinks; i++) LinkSetting[i] = x[i];
free(x); free(x);
return result; return result;
@@ -361,16 +361,16 @@ int nodeoutput(int j, REAL4 *x, double ucf)
switch(j) switch(j)
{ {
case DEMAND: for (i=1; i<=Nnodes; i++) case DEMAND: for (i=1; i<=Nnodes; i++)
x[i] = (REAL4)(D[i]*ucf); x[i] = (REAL4)(NodeDemand[i]*ucf);
break; break;
case HEAD: for (i=1; i<=Nnodes; i++) case HEAD: for (i=1; i<=Nnodes; i++)
x[i] = (REAL4)(H[i]*ucf); x[i] = (REAL4)(NodeHead[i]*ucf);
break; break;
case PRESSURE: for (i=1; i<=Nnodes; i++) case PRESSURE: for (i=1; i<=Nnodes; i++)
x[i] = (REAL4)((H[i] - Node[i].El)*ucf); x[i] = (REAL4)((NodeHead[i] - Node[i].El)*ucf);
break; break;
case QUALITY: for (i=1; i<=Nnodes; i++) case QUALITY: for (i=1; i<=Nnodes; i++)
x[i] = (REAL4)(C[i]*ucf); x[i] = (REAL4)(NodeQual[i]*ucf);
} }
/* Write x[1] to x[Nnodes] to output file */ /* Write x[1] to x[Nnodes] to output file */
@@ -413,10 +413,10 @@ int linkoutput(int j, REAL4 *x, double ucf)
break; break;
case HEADLOSS: for (i=1; i<=Nlinks; i++) case HEADLOSS: for (i=1; i<=Nlinks; i++)
{ {
if (S[i] <= CLOSED) x[i] = 0.0f; if (LinkStatus[i] <= CLOSED) x[i] = 0.0f;
else else
{ {
h = H[Link[i].N1] - H[Link[i].N2]; h = NodeHead[Link[i].N1] - NodeHead[Link[i].N2];
if (Link[i].Type != PUMP) h = ABS(h); if (Link[i].Type != PUMP) h = ABS(h);
if (Link[i].Type <= PIPE) if (Link[i].Type <= PIPE)
x[i] = (REAL4)(1000.0*h/Link[i].Len); x[i] = (REAL4)(1000.0*h/Link[i].Len);
@@ -428,25 +428,26 @@ int linkoutput(int j, REAL4 *x, double ucf)
x[i] = (REAL4)(avgqual(i)*ucf); x[i] = (REAL4)(avgqual(i)*ucf);
break; break;
case STATUS: for (i=1; i<=Nlinks; i++) case STATUS: for (i=1; i<=Nlinks; i++)
x[i] = (REAL4)S[i]; x[i] = (REAL4)LinkStatus[i];
break; break;
case SETTING: for (i=1; i<=Nlinks; i++) case SETTING: for (i=1; i<=Nlinks; i++)
{ {
if (K[i] != MISSING) double setting = LinkSetting[i];
if (setting != MISSING)
switch (Link[i].Type) switch (Link[i].Type)
{ {
case CV: case CV:
case PIPE: x[i] = (REAL4)K[i]; case PIPE: x[i] = (REAL4)setting;
break; break;
case PUMP: x[i] = (REAL4)K[i]; case PUMP: x[i] = (REAL4)setting;
break; break;
case PRV: case PRV:
case PSV: case PSV:
case PBV: x[i] = (REAL4)(K[i]*Ucf[PRESSURE]); case PBV: x[i] = (REAL4)(setting*Ucf[PRESSURE]);
break; break;
case FCV: x[i] = (REAL4)(K[i]*Ucf[FLOW]); case FCV: x[i] = (REAL4)(setting*Ucf[FLOW]);
break; break;
case TCV: x[i] = (REAL4)K[i]; case TCV: x[i] = (REAL4)setting;
break; break;
default: x[i] = 0.0f; default: x[i] = 0.0f;
} }
@@ -455,7 +456,7 @@ int linkoutput(int j, REAL4 *x, double ucf)
break; break;
case REACTRATE: /* Overall reaction rate in mass/L/day */ case REACTRATE: /* Overall reaction rate in mass/L/day */
if (Qualflag == NONE) memset(x,0,(Nlinks+1 )*sizeof(REAL4)); if (Qualflag == NONE) memset(x,0,(Nlinks+1 )*sizeof(REAL4));
else for (i=1; i<=Nlinks; i++) x[i] = (REAL4)(R[i]*ucf); else for (i=1; i<=Nlinks; i++) x[i] = (REAL4)(PipeRateCoeff[i]*ucf);
break; break;
case FRICTION: /* f = 2ghd/(Lu^2) where f = friction factor */ case FRICTION: /* f = 2ghd/(Lu^2) where f = friction factor */
/* u = velocity, g = grav. accel., h = head */ /* u = velocity, g = grav. accel., h = head */
@@ -464,7 +465,7 @@ int linkoutput(int j, REAL4 *x, double ucf)
{ {
if (Link[i].Type <= PIPE && ABS(Q[i]) > TINY) if (Link[i].Type <= PIPE && ABS(Q[i]) > TINY)
{ {
h = ABS(H[Link[i].N1] - H[Link[i].N2]); h = ABS(NodeHead[Link[i].N1] - NodeHead[Link[i].N2]);
f = 39.725*h*pow(Link[i].Diam,5)/Link[i].Len/SQR(Q[i]); f = 39.725*h*pow(Link[i].Diam,5)/Link[i].Len/SQR(Q[i]);
x[i] = (REAL4)f; x[i] = (REAL4)f;
} }
@@ -642,11 +643,11 @@ int savetimestat(REAL4 *x, char objtype)
/* Update internal output variables where applicable */ /* Update internal output variables where applicable */
if (objtype == NODEHDR) switch (j) if (objtype == NODEHDR) switch (j)
{ {
case DEMAND: for (i=1; i<=n; i++) D[i] = x[i]/Ucf[DEMAND]; case DEMAND: for (i=1; i<=n; i++) NodeDemand[i] = x[i]/Ucf[DEMAND];
break; break;
case HEAD: for (i=1; i<=n; i++) H[i] = x[i]/Ucf[HEAD]; case HEAD: for (i=1; i<=n; i++) NodeHead[i] = x[i]/Ucf[HEAD];
break; break;
case QUALITY: for (i=1; i<=n; i++) C[i] = x[i]/Ucf[QUALITY]; case QUALITY: for (i=1; i<=n; i++) NodeQual[i] = x[i]/Ucf[QUALITY];
break; break;
} }
else if (j == FLOW) for (i=1; i<=n; i++) Q[i] = x[i]/Ucf[FLOW]; else if (j == FLOW) for (i=1; i<=n; i++) Q[i] = x[i]/Ucf[FLOW];

View File

@@ -106,10 +106,10 @@ int openqual()
if (SegPool == NULL) errcode = 101; //(2.00.11 - LR) if (SegPool == NULL) errcode = 101; //(2.00.11 - LR)
/* Allocate scratch array & reaction rate array*/ /* Allocate scratch array & reaction rate array*/
XC = (double *) calloc(MAX((Nnodes+1),(Nlinks+1)),sizeof(double)); TempQual = (double *) calloc(MAX((Nnodes+1),(Nlinks+1)),sizeof(double));
R = (double *) calloc((Nlinks+1), sizeof(double)); PipeRateCoeff = (double *) calloc((Nlinks+1), sizeof(double));
ERRCODE(MEMCHECK(XC)); ERRCODE(MEMCHECK(TempQual));
ERRCODE(MEMCHECK(R)); ERRCODE(MEMCHECK(PipeRateCoeff));
/* Allocate memory for WQ solver */ /* Allocate memory for WQ solver */
n = Nlinks+Ntanks+1; n = Nlinks+Ntanks+1;
@@ -148,7 +148,7 @@ void initqual()
int i; int i;
/* Initialize quality, tank volumes, & source mass flows */ /* Initialize quality, tank volumes, & source mass flows */
for (i=1; i<=Nnodes; i++) C[i] = Node[i].C0; for (i=1; i<=Nnodes; i++) NodeQual[i] = Node[i].C0;
for (i=1; i<=Ntanks; i++) Tank[i].C = Node[Tank[i].Node].C0; for (i=1; i<=Ntanks; i++) Tank[i].C = Node[Tank[i].Node].C0;
for (i=1; i<=Ntanks; i++) Tank[i].V = Tank[i].V0; for (i=1; i<=Ntanks; i++) Tank[i].V = Tank[i].V0;
for (i=1; i<=Nnodes; i++) { for (i=1; i<=Nnodes; i++) {
@@ -165,7 +165,7 @@ void initqual()
if (Qualflag != NONE) if (Qualflag != NONE)
{ {
/* Initialize WQ at trace node (if applicable) */ /* Initialize WQ at trace node (if applicable) */
if (Qualflag == TRACE) C[TraceNode] = 100.0; if (Qualflag == TRACE) NodeQual[TraceNode] = 100.0;
/* Compute Schmidt number */ /* Compute Schmidt number */
if (Diffus > 0.0) if (Diffus > 0.0)
@@ -203,6 +203,8 @@ void initqual()
Qtime = 0; Qtime = 0;
Rtime = Rstart; Rtime = Rstart;
Nperiods = 0; Nperiods = 0;
initsegs();
} }
@@ -240,7 +242,7 @@ int runqual(long *t)
for (int i=1; i<= Nlinks; ++i) for (int i=1; i<= Nlinks; ++i)
{ {
if (S[i] <= CLOSED) { if (LinkStatus[i] <= CLOSED) {
QLinkFlow[i-1] = Q[i]; QLinkFlow[i-1] = Q[i];
} }
} }
@@ -255,7 +257,7 @@ int runqual(long *t)
for (int i=1; i<= Nlinks; ++i) for (int i=1; i<= Nlinks; ++i)
{ {
if (S[i] <= CLOSED) { if (LinkStatus[i] <= CLOSED) {
QLinkFlow[i-1] = Q[i]; QLinkFlow[i-1] = Q[i];
} }
} }
@@ -304,13 +306,13 @@ int nextqual(long *tstep)
if (Tank[i].A != 0) { // skip reservoirs again if (Tank[i].A != 0) { // skip reservoirs again
int n = Tank[i].Node; int n = Tank[i].Node;
Tank[i].V = QTankVolumes[i-1]; Tank[i].V = QTankVolumes[i-1];
H[n] = tankgrade(i,Tank[i].V); NodeHead[n] = tankgrade(i,Tank[i].V);
} }
} }
// restore the previous step's pipe link flows // restore the previous step's pipe link flows
for (int i=1; i<=Nlinks; i++) { for (int i=1; i<=Nlinks; i++) {
if (S[i] <= CLOSED) { if (LinkStatus[i] <= CLOSED) {
Q[i] = 0.0; Q[i] = 0.0;
} }
} }
@@ -334,12 +336,12 @@ int nextqual(long *tstep)
if (Tank[i].A != 0) { // skip reservoirs again if (Tank[i].A != 0) { // skip reservoirs again
int n = Tank[i].Node; int n = Tank[i].Node;
Tank[i].V = tankVolumes[i-1]; Tank[i].V = tankVolumes[i-1];
H[n] = tankgrade(i,Tank[i].V); NodeHead[n] = tankgrade(i,Tank[i].V);
} }
} }
for (int i=1; i<=Nlinks; ++i) { for (int i=1; i<=Nlinks; ++i) {
if (S[i] <= CLOSED) { if (LinkStatus[i] <= CLOSED) {
Q[i] = QLinkFlow[i-1]; Q[i] = QLinkFlow[i-1];
} }
} }
@@ -412,8 +414,8 @@ int closequal()
free(FlowDir); free(FlowDir);
free(VolIn); free(VolIn);
free(MassIn); free(MassIn);
free(R); free(PipeRateCoeff);
free(XC); free(TempQual);
free(QTankVolumes); free(QTankVolumes);
free(QLinkFlow); free(QLinkFlow);
return(errcode); return(errcode);
@@ -463,12 +465,20 @@ int gethyd(long *hydtime, long *hydstep)
{ {
/* Compute reaction rate coeffs. */ /* Compute reaction rate coeffs. */
if (Reactflag && Qualflag != AGE) ratecoeffs(); if (Reactflag && Qualflag != AGE) {
ratecoeffs();
}
/* Initialize pipe segments (at time 0) or */ /* Initialize pipe segments (at time 0) or */
/* else re-orient segments if flow reverses.*/ /* else re-orient segments if flow reverses.*/
if (Qtime == 0) initsegs(); //if (Qtime == 0)
else reorientsegs(); // initsegs();
//else
// if hydraulics are open, or if we're in sequential mode (where qtime can increase)
if (OpenHflag || Qtime != 0) {
reorientsegs();
}
} }
return(errcode); return(errcode);
} }
@@ -550,8 +560,10 @@ void initsegs()
{ {
/* Establish flow direction */ /* Establish flow direction */
FlowDir[k] = '+'; FlowDir[k] = '+';
if (Q[k] < 0.) FlowDir[k] = '-'; if (Q[k] < 0.) {
FlowDir[k] = '-';
}
/* Set segs to zero */ /* Set segs to zero */
LastSeg[k] = NULL; LastSeg[k] = NULL;
@@ -559,7 +571,7 @@ void initsegs()
/* Find quality of downstream node */ /* Find quality of downstream node */
j = DOWN_NODE(k); j = DOWN_NODE(k);
if (j <= Njuncs) c = C[j]; if (j <= Njuncs) c = NodeQual[j];
else c = Tank[j-Njuncs].C; else c = Tank[j-Njuncs].C;
/* Fill link with single segment with this quality */ /* Fill link with single segment with this quality */
@@ -617,9 +629,13 @@ void reorientsegs()
{ {
/* Find new flow direction */ /* Find new flow direction */
newdir = '+'; newdir = '+';
if (Q[k] == 0.0) newdir = FlowDir[k]; if (Q[k] == 0.0) {
else if (Q[k] < 0.0) newdir = '-'; newdir = FlowDir[k];
}
else if (Q[k] < 0.0) {
newdir = '-';
}
/* If direction changes, then reverse order of segments */ /* If direction changes, then reverse order of segments */
/* (first to last) and save new direction */ /* (first to last) and save new direction */
@@ -683,8 +699,8 @@ void updatesegs(long dt)
} }
/* Normalize volume-weighted reaction rate */ /* Normalize volume-weighted reaction rate */
if (vsum > 0.0) R[k] = rsum/vsum/dt*SECperDAY; if (vsum > 0.0) PipeRateCoeff[k] = rsum/vsum/dt*SECperDAY;
else R[k] = 0.0; else PipeRateCoeff[k] = 0.0;
} }
} }
@@ -765,7 +781,7 @@ void accumulate(long dt)
/* Re-set memory used to accumulate mass & volume */ /* Re-set memory used to accumulate mass & volume */
memset(VolIn,0,(Nnodes+1)*sizeof(double)); memset(VolIn,0,(Nnodes+1)*sizeof(double));
memset(MassIn,0,(Nnodes+1)*sizeof(double)); memset(MassIn,0,(Nnodes+1)*sizeof(double));
memset(XC,0,(Nnodes+1)*sizeof(double)); memset(TempQual,0,(Nnodes+1)*sizeof(double));
/* Compute average conc. of segments adjacent to each node */ /* Compute average conc. of segments adjacent to each node */
/* (For use if there is no transport through the node) */ /* (For use if there is no transport through the node) */
@@ -784,9 +800,13 @@ void accumulate(long dt)
VolIn[j]++; VolIn[j]++;
} }
} }
for (k=1; k<=Nnodes; k++)
if (VolIn[k] > 0.0) XC[k] = MassIn[k]/VolIn[k]; for (k=1; k<=Nnodes; k++) {
if (VolIn[k] > 0.0) {
TempQual[k] = MassIn[k]/VolIn[k];
}
}
/* Move mass from first segment of each pipe into downstream node */ /* Move mass from first segment of each pipe into downstream node */
memset(VolIn,0,(Nnodes+1)*sizeof(double)); memset(VolIn,0,(Nnodes+1)*sizeof(double));
memset(MassIn,0,(Nnodes+1)*sizeof(double)); memset(MassIn,0,(Nnodes+1)*sizeof(double));
@@ -804,7 +824,7 @@ void accumulate(long dt)
{ {
VolIn[j] += v; VolIn[j] += v;
seg = FirstSeg[k]; seg = FirstSeg[k];
cseg = C[i]; cseg = NodeQuali];
if (seg != NULL) cseg = seg->c; if (seg != NULL) cseg = seg->c;
MassIn[j] += v*cseg; MassIn[j] += v*cseg;
removesegs(k); removesegs(k);
@@ -866,27 +886,33 @@ void updatenodes(long dt)
** Purpose: updates concentration at all nodes to mixture of accumulated ** Purpose: updates concentration at all nodes to mixture of accumulated
** inflow from connecting pipes. ** inflow from connecting pipes.
** **
** Note: Does not account for source flow effects. XC[i] contains ** Note: Does not account for source flow effects. TempQual[i] contains
** average concen. of segments adjacent to node i, used in case ** average concen. of segments adjacent to node i, used in case
** there was no inflow into i. ** there was no inflow into i.
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
*/ */
{ {
int i; int i;
/* Update junction quality */ /* Update junction quality */
for (i=1; i<=Njuncs; i++) for (i=1; i<=Njuncs; i++)
{ {
if (D[i] < 0.0) VolIn[i] -= D[i]*dt; if (NodeDemand[i] < 0.0) {
if (VolIn[i] > 0.0) C[i] = MassIn[i]/VolIn[i]; VolIn[i] -= NodeDemand[i]*dt;
else C[i] = XC[i]; }
} if (VolIn[i] > 0.0) {
NodeQual[i] = MassIn[i]/VolIn[i];
/* Update tank quality */ }
updatetanks(dt); else {
NodeQual[i] = TempQual[i];
/* For flow tracing, set source node concen. to 100. */ }
if (Qualflag == TRACE) C[TraceNode] = 100.0; }
/* Update tank quality */
updatetanks(dt);
/* For flow tracing, set source node concen. to 100. */
if (Qualflag == TRACE) NodeQual[TraceNode] = 100.0;
} }
@@ -908,14 +934,14 @@ void sourceinput(long dt)
/* Establish a flow cutoff which indicates no outflow from a node */ /* Establish a flow cutoff which indicates no outflow from a node */
qcutoff = 10.0*TINY; qcutoff = 10.0*TINY;
/* Zero-out the work array XC */ /* Zero-out the work array TempQual */
memset(XC,0,(Nnodes+1)*sizeof(double)); memset(TempQual,0,(Nnodes+1)*sizeof(double));
if (Qualflag != CHEM) return; if (Qualflag != CHEM) return;
/* Consider each node */ /* Consider each node */
for (n=1; n<=Nnodes; n++) for (n=1; n<=Nnodes; n++)
{ {
double thisDemand = NodeDemand[n];
/* Skip node if no WQ source */ /* Skip node if no WQ source */
source = Node[n].S; source = Node[n].S;
if (source == NULL) continue; if (source == NULL) continue;
@@ -923,7 +949,7 @@ void sourceinput(long dt)
/* Find total flow volume leaving node */ /* Find total flow volume leaving node */
if (n <= Njuncs) volout = VolIn[n]; /* Junctions */ if (n <= Njuncs) volout = VolIn[n]; /* Junctions */
else volout = VolIn[n] - D[n]*dt; /* Tanks */ else volout = VolIn[n] - (thisDemand * dt); /* Tanks */
qout = volout / (double) dt; qout = volout / (double) dt;
/* Evaluate source input only if node outflow > cutoff flow */ /* Evaluate source input only if node outflow > cutoff flow */
@@ -939,13 +965,13 @@ void sourceinput(long dt)
case CONCEN: case CONCEN:
/* Only add source mass if demand is negative */ /* Only add source mass if demand is negative */
if (D[n] < 0.0) if (thisDemand < 0.0)
{ {
massadded = -s*D[n]*dt; massadded = -s*thisDemand*dt;
/* If node is a tank then set concen. to 0. */ /* If node is a tank then set concen. to 0. */
/* (It will be re-set to true value in updatesourcenodes()) */ /* (It will be re-set to true value in updatesourcenodes()) */
if (n > Njuncs) C[n] = 0.0; if (n > Njuncs) NodeQual[n] = 0.0;
} }
else massadded = 0.0; else massadded = 0.0;
break; break;
@@ -959,9 +985,13 @@ void sourceinput(long dt)
/* Mass added is difference between source */ /* Mass added is difference between source */
/* & node concen. times outflow volume */ /* & node concen. times outflow volume */
case SETPOINT: case SETPOINT:
if (s > C[n]) massadded = (s-C[n])*volout; if (s > NodeQual[n]) {
else massadded = 0.0; massadded = (s-NodeQual[n])*volout;
break; }
else {
massadded = 0.0;
}
break;
/* Flow-Paced Booster Source: */ /* Flow-Paced Booster Source: */
/* Mass added = source concen. times outflow volume */ /* Mass added = source concen. times outflow volume */
@@ -971,7 +1001,7 @@ void sourceinput(long dt)
} }
/* Source concen. contribution = (mass added / outflow volume) */ /* Source concen. contribution = (mass added / outflow volume) */
XC[n] = massadded/volout; TempQual[n] = massadded/volout;
/* Update total mass added for time period & simulation */ /* Update total mass added for time period & simulation */
source->Smass += massadded; source->Smass += massadded;
@@ -987,8 +1017,8 @@ void sourceinput(long dt)
if (Tank[j].A == 0.0) if (Tank[j].A == 0.0)
{ {
n = Njuncs + j; n = Njuncs + j;
volout = VolIn[n] - D[n]*dt; volout = VolIn[n] - NodeDemand[n]*dt;
if (volout > 0.0) Wsource += volout*C[n]; if (volout > 0.0) Wsource += volout*NodeQual[n];
} }
} }
} }
@@ -1022,7 +1052,7 @@ void release(long dt)
v = q*dt; v = q*dt;
/* Include source contribution in quality released from node. */ /* Include source contribution in quality released from node. */
c = C[n] + XC[n]; c = NodeQual[n] + TempQual[n];
/* If link has a last seg, check if its quality */ /* If link has a last seg, check if its quality */
/* differs from that of the flow released from node.*/ /* differs from that of the flow released from node.*/
@@ -1051,7 +1081,7 @@ void updatesourcenodes(long dt)
** Input: dt = current WQ time step ** Input: dt = current WQ time step
** Output: none ** Output: none
** Purpose: updates quality at source nodes. ** Purpose: updates quality at source nodes.
** (XC[n] = concen. added by source at node n) ** (TempQual[n] = concen. added by source at node n)
**--------------------------------------------------- **---------------------------------------------------
*/ */
{ {
@@ -1067,13 +1097,13 @@ void updatesourcenodes(long dt)
if (source == NULL) continue; if (source == NULL) continue;
/* Add source to current node concen. */ /* Add source to current node concen. */
C[n] += XC[n]; NodeQual[n] += TempQual[n];
/* For tanks, node concen. = internal concen. */ /* For tanks, node concen. = internal concen. */
if (n > Njuncs) if (n > Njuncs)
{ {
i = n - Njuncs; i = n - Njuncs;
if (Tank[i].A > 0.0) C[n] = Tank[i].C; if (Tank[i].A > 0.0) NodeQual[n] = Tank[i].C;
} }
/* Normalize mass added at source to time step */ /* Normalize mass added at source to time step */
@@ -1100,7 +1130,7 @@ void updatetanks(long dt)
/* Use initial quality for reservoirs */ /* Use initial quality for reservoirs */
if (Tank[i].A == 0.0) if (Tank[i].A == 0.0)
{ {
C[n] = Node[n].C0; NodeQual[n] = Node[n].C0;
} }
/* Update tank WQ based on mixing model */ /* Update tank WQ based on mixing model */
else { else {
@@ -1143,7 +1173,7 @@ void updatetanks(long dt)
// /* Update tank volume & nodal quality */ // /* Update tank volume & nodal quality */
// Tank[i].V += D[n]*dt; // Tank[i].V += D[n]*dt;
// C[n] = Tank[i].C; // NodeQual[n] = Tank[i].C;
//} //}
@@ -1168,7 +1198,7 @@ void tankmix1(int i, long dt)
/* Determine tank & volumes */ /* Determine tank & volumes */
vold = Tank[i].V; vold = Tank[i].V;
n = Tank[i].Node; n = Tank[i].Node;
Tank[i].V += D[n]*dt; Tank[i].V += NodeDemand[n]*dt;
vin = VolIn[n]; vin = VolIn[n];
/* Compute inflow concen. */ /* Compute inflow concen. */
@@ -1181,7 +1211,7 @@ void tankmix1(int i, long dt)
c = MIN(c, cmax); c = MIN(c, cmax);
c = MAX(c, 0.0); c = MAX(c, 0.0);
Tank[i].C = c; Tank[i].C = c;
C[n] = Tank[i].C; NodeQual[n] = Tank[i].C;
} }
/*** Updated 10/25/00 ***/ /*** Updated 10/25/00 ***/
@@ -1218,7 +1248,7 @@ void tankmix2(int i, long dt)
/* Find inflows & outflows */ /* Find inflows & outflows */
n = Tank[i].Node; n = Tank[i].Node;
vnet = D[n]*dt; vnet = NodeDemand[n]*dt;
vin = VolIn[n]; vin = VolIn[n];
if (vin > 0.0) cin = MassIn[n]/vin; if (vin > 0.0) cin = MassIn[n]/vin;
else cin = 0.0; else cin = 0.0;
@@ -1274,7 +1304,7 @@ void tankmix2(int i, long dt)
/* represent quality of tank since this is where */ /* represent quality of tank since this is where */
/* outflow begins to flow from */ /* outflow begins to flow from */
Tank[i].C = seg1->c; Tank[i].C = seg1->c;
C[n] = Tank[i].C; NodeQual[n] = Tank[i].C;
} }
@@ -1309,7 +1339,7 @@ void tankmix3(int i, long dt)
/* Find inflows & outflows */ /* Find inflows & outflows */
n = Tank[i].Node; n = Tank[i].Node;
vnet = D[n]*dt; vnet = NodeDemand[n]*dt;
vin = VolIn[n]; vin = VolIn[n];
vout = vin - vnet; vout = vin - vnet;
if (vin > 0.0) cin = MassIn[n]/VolIn[n]; if (vin > 0.0) cin = MassIn[n]/VolIn[n];
@@ -1350,7 +1380,7 @@ void tankmix3(int i, long dt)
/* to represent overall quality of tank */ /* to represent overall quality of tank */
if (vsum > 0.0) Tank[i].C = csum/vsum; if (vsum > 0.0) Tank[i].C = csum/vsum;
else Tank[i].C = FirstSeg[k]->c; else Tank[i].C = FirstSeg[k]->c;
C[n] = Tank[i].C; NodeQual[n] = Tank[i].C;
/* Add new last segment for new flow entering tank */ /* Add new last segment for new flow entering tank */
if (vin > 0.0) if (vin > 0.0)
@@ -1400,7 +1430,7 @@ void tankmix4(int i, long dt)
/* Find inflows & outflows */ /* Find inflows & outflows */
n = Tank[i].Node; n = Tank[i].Node;
vnet = D[n]*dt; vnet = NodeDemand[n]*dt;
vin = VolIn[n]; vin = VolIn[n];
if (vin > 0.0) cin = MassIn[n]/VolIn[n]; if (vin > 0.0) cin = MassIn[n]/VolIn[n];
else cin = 0.0; else cin = 0.0;
@@ -1468,7 +1498,7 @@ void tankmix4(int i, long dt)
/* Reported tank quality is mixture of flow released and any inflow */ /* Reported tank quality is mixture of flow released and any inflow */
Tank[i].C = (csum + MassIn[n])/(vsum + vin); Tank[i].C = (csum + MassIn[n])/(vsum + vin);
} }
C[n] = Tank[i].C; NodeQual[n] = Tank[i].C;
} }
@@ -1523,7 +1553,7 @@ double avgqual(int k)
seg = seg->prev; seg = seg->prev;
} }
if (vsum > 0.0) return(msum/vsum); if (vsum > 0.0) return(msum/vsum);
else return( (C[Link[k].N1] + C[Link[k].N2])/2. ); else return( (NodeQual[Link[k].N1] + NodeQual[Link[k].N2])/2. );
} }
@@ -1544,7 +1574,7 @@ void ratecoeffs()
kw = Link[k].Kw; kw = Link[k].Kw;
if (kw != 0.0) kw = piperate(k); if (kw != 0.0) kw = piperate(k);
Link[k].Rc = kw; Link[k].Rc = kw;
R[k] = 0.0; PipeRateCoeff[k] = 0.0;
} }
} /* End of ratecoeffs */ } /* End of ratecoeffs */

View File

@@ -296,15 +296,15 @@ void writehydstat(int iter, double relerr)
for (i=1; i<=Ntanks; i++) for (i=1; i<=Ntanks; i++)
{ {
n = Tank[i].Node; n = Tank[i].Node;
if (ABS(D[n]) < 0.001) newstat = CLOSED; if (ABS(NodeDemand[n]) < 0.001) newstat = CLOSED;
else if (D[n] > 0.0) newstat = FILLING; else if (NodeDemand[n] > 0.0) newstat = FILLING;
else if (D[n] < 0.0) newstat = EMPTYING; else if (NodeDemand[n] < 0.0) newstat = EMPTYING;
else newstat = OldStat[Nlinks+i]; else newstat = OldStat[Nlinks+i];
if (newstat != OldStat[Nlinks+i]) if (newstat != OldStat[Nlinks+i])
{ {
if (Tank[i].A > 0.0) if (Tank[i].A > 0.0)
sprintf(s1,FMT50,atime,Node[n].ID,StatTxt[newstat], sprintf(s1,FMT50,atime,Node[n].ID,StatTxt[newstat],
(H[n]-Node[n].El)*Ucf[HEAD],Field[HEAD].Units); (NodeHead[n]-Node[n].El)*Ucf[HEAD],Field[HEAD].Units);
else sprintf(s1,FMT51,atime,Node[n].ID,StatTxt[newstat]); else sprintf(s1,FMT51,atime,Node[n].ID,StatTxt[newstat]);
writeline(s1); writeline(s1);
OldStat[Nlinks+i] = newstat; OldStat[Nlinks+i] = newstat;
@@ -314,15 +314,15 @@ void writehydstat(int iter, double relerr)
/* Display status changes for links */ /* Display status changes for links */
for (i=1; i<=Nlinks; i++) for (i=1; i<=Nlinks; i++)
{ {
if (S[i] != OldStat[i]) if (LinkStatus[i] != OldStat[i])
{ {
if (Htime == 0) if (Htime == 0)
sprintf(s1,FMT52,atime,LinkTxt[Link[i].Type],Link[i].ID, sprintf(s1,FMT52,atime,LinkTxt[Link[i].Type],Link[i].ID,
StatTxt[S[i]]); StatTxt[LinkStatus[i]]);
else sprintf(s1,FMT53,atime,LinkTxt[Link[i].Type],Link[i].ID, else sprintf(s1,FMT53,atime,LinkTxt[Link[i].Type],Link[i].ID,
StatTxt[OldStat[i]],StatTxt[S[i]]); StatTxt[OldStat[i]],StatTxt[LinkStatus[i]]);
writeline(s1); writeline(s1);
OldStat[i] = S[i]; OldStat[i] = LinkStatus[i];
} }
} }
writeline(" "); writeline(" ");
@@ -763,7 +763,7 @@ void writestatchange(int k, char s1, char s2)
{ {
/*** Updated 10/25/00 ***/ /*** Updated 10/25/00 ***/
setting = K[k]; //Link[k].Kc; setting = LinkSetting[k]; //Link[k].Kc;
switch (Link[k].Type) switch (Link[k].Type)
{ {
@@ -871,7 +871,7 @@ int writehydwarn(int iter, double relerr)
/* Check for negative pressures */ /* Check for negative pressures */
for (i=1; i<=Njuncs; i++) for (i=1; i<=Njuncs; i++)
{ {
if (H[i] < Node[i].El && D[i] > 0.0) if (NodeHead[i] < Node[i].El && NodeDemand[i] > 0.0)
{ {
sprintf(Msg,WARN06,clocktime(Atime,Htime)); sprintf(Msg,WARN06,clocktime(Atime,Htime));
if (Messageflag) writeline(Msg); if (Messageflag) writeline(Msg);
@@ -884,10 +884,10 @@ int writehydwarn(int iter, double relerr)
for (i=1; i<=Nvalves; i++) for (i=1; i<=Nvalves; i++)
{ {
j = Valve[i].Link; j = Valve[i].Link;
if (S[j] >= XFCV) if (LinkStatus[j] >= XFCV)
{ {
sprintf(Msg,WARN05,LinkTxt[Link[j].Type],Link[j].ID, sprintf(Msg,WARN05,LinkTxt[Link[j].Type],Link[j].ID,
StatTxt[S[j]],clocktime(Atime,Htime)); StatTxt[LinkStatus[j]],clocktime(Atime,Htime));
if (Messageflag) writeline(Msg); if (Messageflag) writeline(Msg);
flag = 5; flag = 5;
} }
@@ -897,10 +897,10 @@ int writehydwarn(int iter, double relerr)
for (i=1; i<=Npumps; i++) for (i=1; i<=Npumps; i++)
{ {
j = Pump[i].Link; j = Pump[i].Link;
s = S[j]; //(2.00.11 - LR) s = LinkStatus[j]; //(2.00.11 - LR)
if (S[j] >= OPEN) //(2.00.11 - LR) if (LinkStatus[j] >= OPEN) //(2.00.11 - LR)
{ //(2.00.11 - LR) { //(2.00.11 - LR)
if (Q[j] > K[j]*Pump[i].Qmax) s = XFLOW; //(2.00.11 - LR) if (Q[j] > LinkSetting[j]*Pump[i].Qmax) s = XFLOW; //(2.00.11 - LR)
if (Q[j] < 0.0) s = XHEAD; //(2.00.11 - LR) if (Q[j] < 0.0) s = XHEAD; //(2.00.11 - LR)
} //(2.00.11 - LR) } //(2.00.11 - LR)
if (s == XHEAD || s == XFLOW) //(2.00.11 - LR) if (s == XHEAD || s == XFLOW) //(2.00.11 - LR)
@@ -984,7 +984,7 @@ int disconnected()
mcount = Ntanks; mcount = Ntanks;
for (i=1; i<=Njuncs; i++) for (i=1; i<=Njuncs; i++)
{ {
if (D[i] < 0.0) if (NodeDemand[i] < 0.0)
{ {
mcount++; mcount++;
nodelist[mcount] = i; nodelist[mcount] = i;
@@ -999,7 +999,7 @@ int disconnected()
count = 0; count = 0;
for (i=1; i<=Njuncs; i++) for (i=1; i<=Njuncs; i++)
{ {
if (!marked[i] && D[i] != 0.0) /* Skip if no demand */ if (!marked[i] && NodeDemand[i] != 0.0) /* Skip if no demand */
{ {
count++; count++;
if (count <= MAXCOUNT && Messageflag) if (count <= MAXCOUNT && Messageflag)
@@ -1068,7 +1068,7 @@ void marknodes(int m, int *nodelist, char *marked)
} }
/* Mark connection node if link not closed */ /* Mark connection node if link not closed */
if (S[k] > CLOSED) if (LinkStatus[k] > CLOSED)
{ {
marked[j] = 1; marked[j] = 1;
m++; m++;

View File

@@ -704,7 +704,7 @@ int checkstatus(struct Premise *p)
case IS_OPEN: case IS_OPEN:
case IS_CLOSED: case IS_CLOSED:
case IS_ACTIVE: case IS_ACTIVE:
i = S[p->index]; i = LinkStatus[p->index];
if (i <= CLOSED) j = IS_CLOSED; if (i <= CLOSED) j = IS_CLOSED;
else if (i == ACTIVE) j = IS_ACTIVE; else if (i == ACTIVE) j = IS_ACTIVE;
else j = IS_OPEN; else j = IS_OPEN;
@@ -736,20 +736,20 @@ int checkvalue(struct Premise *p)
/*** Updated 10/25/00 ***/ /*** Updated 10/25/00 ***/
case r_DEMAND: if (p->object == r_SYSTEM) x = Dsystem*Ucf[DEMAND]; case r_DEMAND: if (p->object == r_SYSTEM) x = Dsystem*Ucf[DEMAND];
else x = D[i]*Ucf[DEMAND]; else x = NodeDemand[i]*Ucf[DEMAND];
break; break;
case r_HEAD: case r_HEAD:
case r_GRADE: x = H[i]*Ucf[HEAD]; case r_GRADE: x = NodeHead[i]*Ucf[HEAD];
break; break;
case r_PRESSURE: x = (H[i]-Node[i].El)*Ucf[PRESSURE]; case r_PRESSURE: x = (NodeHead[i]-Node[i].El)*Ucf[PRESSURE];
break; break;
case r_LEVEL: x = (H[i]-Node[i].El)*Ucf[HEAD]; case r_LEVEL: x = (NodeHead[i]-Node[i].El)*Ucf[HEAD];
break; break;
case r_FLOW: x = ABS(Q[i])*Ucf[FLOW]; case r_FLOW: x = ABS(Q[i])*Ucf[FLOW];
break; break;
case r_SETTING: if (K[i] == MISSING) return(0); case r_SETTING: if (LinkSetting[i] == MISSING) return(0);
x = K[i]; x = LinkSetting[i];
switch (Link[i].Type) switch (Link[i].Type)
{ {
case PRV: case PRV:
@@ -761,14 +761,14 @@ int checkvalue(struct Premise *p)
case r_FILLTIME: if (i <= Njuncs) return(0); case r_FILLTIME: if (i <= Njuncs) return(0);
j = i-Njuncs; j = i-Njuncs;
if (Tank[j].A == 0.0) return(0); if (Tank[j].A == 0.0) return(0);
if (D[i] <= TINY) return(0); if (NodeDemand[i] <= TINY) return(0);
x = (Tank[j].Vmax - Tank[j].V)/D[i]; x = (Tank[j].Vmax - Tank[j].V)/NodeDemand[i];
break; break;
case r_DRAINTIME: if (i <= Njuncs) return(0); case r_DRAINTIME: if (i <= Njuncs) return(0);
j = i-Njuncs; j = i-Njuncs;
if (Tank[j].A == 0.0) return(0); if (Tank[j].A == 0.0) return(0);
if (D[i] >= -TINY) return(0); if (NodeDemand[i] >= -TINY) return(0);
x = (Tank[j].Vmin - Tank[j].V)/D[i]; x = (Tank[j].Vmin - Tank[j].V)/NodeDemand[i];
break; break;
default: return(0); default: return(0);
} }
@@ -875,21 +875,21 @@ int takeactions()
flag = FALSE; flag = FALSE;
a = item->action; a = item->action;
k = a->link; k = a->link;
s = S[k]; s = LinkStatus[k];
v = K[k]; v = LinkSetting[k];
x = a->setting; x = a->setting;
/* Switch link from closed to open */ /* Switch link from closed to open */
if (a->status == IS_OPEN && s <= CLOSED) if (a->status == IS_OPEN && s <= CLOSED)
{ {
setlinkstatus(k, 1, &S[k], &K[k]); setlinkstatus(k, 1, &LinkStatus[k], &LinkSetting[k]);
flag = TRUE; flag = TRUE;
} }
/* Switch link from not closed to closed */ /* Switch link from not closed to closed */
else if (a->status == IS_CLOSED && s > CLOSED) else if (a->status == IS_CLOSED && s > CLOSED)
{ {
setlinkstatus(k, 0, &S[k], &K[k]); setlinkstatus(k, 0, &LinkStatus[k], &LinkSetting[k]);
flag = TRUE; flag = TRUE;
} }
@@ -905,7 +905,7 @@ int takeactions()
} }
if (ABS(x-v) > tol) if (ABS(x-v) > tol)
{ {
setlinksetting(k, x, &S[k], &K[k]); setlinksetting(k, x, &LinkStatus[k], &LinkSetting[k]);
flag = TRUE; flag = TRUE;
} }
} }

View File

@@ -144,17 +144,17 @@ AUTHOR: L. Rossman
SField Field[MAXVAR]; /* Output reporting fields */ SField Field[MAXVAR]; /* Output reporting fields */
/* Array pointers not allocated and freed in same routine */ /* Array pointers not allocated and freed in same routine */
char *S, /* Link status */ char *LinkStatus, /* Link status */
*OldStat; /* Previous link/tank status */ *OldStat; /* Previous link/tank status */
double *D, /* Node actual demand */ double *NodeDemand, /* Node actual demand */
*C, /* Node actual quality */ *NodeQual, /* Node actual quality */
*E, /* Emitter flows */ *E, /* Emitter flows */
*K, /* Link settings */ *LinkSetting, /* Link settings */
*Q, /* Link flows */ *Q, /* Link flows */
*R, /* Pipe reaction rate */ *PipeRateCoeff, /* Pipe reaction rate */
*X, /* General purpose array */ *X, /* General purpose array */
*XC; /* General purpose array */ *TempQual; /* General purpose array for water quality */
EXTERN double *H; /* Node heads */ EXTERN double *NodeHead; /* Node heads */
EXTERN double *QTankVolumes; EXTERN double *QTankVolumes;
EXTERN double *QLinkFlow; EXTERN double *QLinkFlow;
EXTERN STmplist *Patlist; /* Temporary time pattern list */ EXTERN STmplist *Patlist; /* Temporary time pattern list */
@@ -171,7 +171,8 @@ EXTERN Svalve *Valve; /* Valve data */
EXTERN Scontrol *Control; /* Control data */ EXTERN Scontrol *Control; /* Control data */
EXTERN HTtable *Nht, *Lht; /* Hash tables for ID labels */ EXTERN HTtable *Nht, *Lht; /* Hash tables for ID labels */
EXTERN Padjlist *Adjlist; /* Node adjacency lists */ EXTERN Padjlist *Adjlist; /* Node adjacency lists */
EXTERN int _relativeError, _iterations; /* Info about hydraulic solution */ EXTERN double _relativeError;
EXTERN int _iterations; /* Info about hydraulic solution */
/* /*
** NOTE: Hydraulic analysis of the pipe network at a given point in time ** NOTE: Hydraulic analysis of the pipe network at a given point in time

0
test/Net3.inp Normal file → Executable file
View File

0
test/simplenet.inp Normal file → Executable file
View File