Merge pull request #360 from LRossman/lrossman-dev

Error reporting fixes and re-formatting (issue #358)
This commit is contained in:
Lew Rossman
2018-12-17 13:13:08 -05:00
committed by GitHub
9 changed files with 428 additions and 396 deletions

View File

@@ -7,7 +7,7 @@
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 11/27/2018
Last Updated: 12/15/2018
******************************************************************************
*/
@@ -26,7 +26,9 @@
#include "text.h"
#include "enumstxt.h"
#ifdef WINDOWS
#define snprintf _snprintf
#endif
/********************************************************************
@@ -841,7 +843,7 @@ int DLLEXPORT EN_setstatusreport(EN_Project p, int code)
{
p->report.Statflag = (char)code;
}
else errcode = 202;
else errcode = 251;
return errcode;
}
@@ -915,7 +917,8 @@ int DLLEXPORT EN_geterror(int errcode, char *errmsg, int n)
**----------------------------------------------------------------
*/
{
char newMsg[MAXMSG + 1];
char msg1[MAXMSG+1] = "";
char msg2[MAXMSG+1] = "";
switch (errcode)
{
@@ -938,8 +941,10 @@ int DLLEXPORT EN_geterror(int errcode, char *errmsg, int n)
strncpy(errmsg, WARN6, n);
break;
default:
geterrmsg(errcode, newMsg);
strncpy(errmsg, newMsg, n);
sprintf(msg1, "Error %d: ", errcode);
if ((errcode >= 202 && errcode <= 222) ||
(errcode >= 240 && errcode <= 261)) strcat(msg1, "function call contains ");
snprintf(errmsg, n, "%s%s", msg1, geterrmsg(errcode, msg2));
}
if (strlen(errmsg) == 0)
return 251;
@@ -974,6 +979,7 @@ int DLLEXPORT EN_getstatistic(EN_Project p, int code, EN_API_FLOAT_TYPE *value)
*value = (EN_API_FLOAT_TYPE)(p->quality.MassBalance.ratio);
break;
default:
*value = 0.0;
break;
}
return 0;
@@ -1067,22 +1073,22 @@ int DLLEXPORT EN_setoption(EN_Project p, int code, EN_API_FLOAT_TYPE v)
switch (code)
{
case EN_TRIALS:
if (value < 1.0) return 202;
if (value < 1.0) return 213;
hyd->MaxIter = (int)value;
break;
case EN_ACCURACY:
if (value < 1.e-5 || value > 1.e-1) return 202;
if (value < 1.e-5 || value > 1.e-1) return 213;
hyd->Hacc = value;
break;
case EN_TOLERANCE:
if (value < 0.0) return 202;
if (value < 0.0) return 213;
qual->Ctol = value / Ucf[QUALITY];
break;
case EN_EMITEXPON:
if (value <= 0.0) return 202;
if (value <= 0.0) return 213;
n = 1.0 / value;
ucf = pow(Ucf[FLOW], n) / Ucf[PRESSURE];
for (i = 1; i <= Njuncs; i++)
@@ -1095,17 +1101,17 @@ int DLLEXPORT EN_setoption(EN_Project p, int code, EN_API_FLOAT_TYPE v)
break;
case EN_DEMANDMULT:
if (value <= 0.0) return 202;
if (value <= 0.0) return 213;
hyd->Dmult = value;
break;
case EN_HEADERROR:
if (value < 0.0) return 202;
if (value < 0.0) return 213;
hyd->HeadErrorLimit = value / Ucf[HEAD];
break;
case EN_FLOWCHANGE:
if (value < 0.0) return 202;
if (value < 0.0) return 213;
hyd->FlowChangeLimit = value / Ucf[FLOW];
break;
@@ -1319,7 +1325,7 @@ int DLLEXPORT EN_settimeparam(EN_Project p, int code, long value)
Times *time = &p->times;
if (!p->Openflag) return 102;
if (value < 0) return 202;
if (value < 0) return 213;
switch (code)
{
case EN_DURATION:
@@ -1328,7 +1334,7 @@ int DLLEXPORT EN_settimeparam(EN_Project p, int code, long value)
break;
case EN_HYDSTEP:
if (value == 0) return 202;
if (value == 0) return 213;
time->Hstep = value;
time->Hstep = MIN(time->Pstep, time->Hstep);
time->Hstep = MIN(time->Rstep, time->Hstep);
@@ -1336,13 +1342,13 @@ int DLLEXPORT EN_settimeparam(EN_Project p, int code, long value)
break;
case EN_QUALSTEP:
if (value == 0) return 202;
if (value == 0) return 213;
time->Qstep = value;
time->Qstep = MIN(time->Qstep, time->Hstep);
break;
case EN_PATTERNSTEP:
if (value == 0) return 202;
if (value == 0) return 213;
time->Pstep = value;
if (time->Hstep > time->Pstep) time->Hstep = time->Pstep;
break;
@@ -1352,24 +1358,24 @@ int DLLEXPORT EN_settimeparam(EN_Project p, int code, long value)
break;
case EN_REPORTSTEP:
if (value == 0) return 202;
if (value == 0) return 213;
time->Rstep = value;
if (time->Hstep > time->Rstep) time->Hstep = time->Rstep;
break;
case EN_REPORTSTART:
if (time->Rstart > time->Dur) return 202;
if (time->Rstart > time->Dur) return 213;
time->Rstart = value;
break;
case EN_RULESTEP:
if (value == 0) return 202;
if (value == 0) return 213;
time->Rulestep = value;
time->Rulestep = MIN(time->Rulestep, time->Hstep);
break;
case EN_STATISTIC:
if (value > RANGE) return 202;
if (value > RANGE) return 213;
rpt->Tstatflag = (char)value;
break;
@@ -1401,16 +1407,26 @@ int DLLEXPORT EN_getqualinfo(EN_Project p, int *qualcode, char *chemname,
*/
{
EN_getqualtype(p, qualcode, tracenode);
if (p->quality.Qualflag == TRACE)
{
strncpy(chemname, "", MAXID);
strncpy(chemunits, "dimensionless", MAXID);
}
else
if (p->quality.Qualflag == CHEM)
{
strncpy(chemname, p->quality.ChemName, MAXID);
strncpy(chemunits, p->quality.ChemUnits, MAXID);
}
else if (p->quality.Qualflag == TRACE)
{
strncpy(chemname, w_TRACE, MAXID);
strncpy(chemunits, u_PERCENT, MAXID);
}
else if (p->quality.Qualflag == AGE)
{
strncpy(chemname, w_AGE, MAXID);
strncpy(chemunits, u_HOURS, MAXID);
}
else
{
strncpy(chemname, "", MAXID);
strncpy(chemunits, "", MAXID);
}
return 0;
}
@@ -1469,9 +1485,9 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualcode, char *chemname,
if (qual->Qualflag == TRACE) // Source trace analysis
{
qual->TraceNode = findnode(net, tracenode);
if (qual->TraceNode == 0) return 203;
strncpy(qual->ChemName, u_PERCENT, MAXID);
strncpy(qual->ChemUnits, tracenode, MAXID);
if (qual->TraceNode == 0) return 212;
strncpy(qual->ChemName, w_TRACE, MAXID);
strncpy(qual->ChemUnits, u_PERCENT, MAXID);
strcpy(rpt->Field[QUALITY].Units, u_PERCENT);
}
if (qual->Qualflag == AGE) // Water age analysis
@@ -1656,7 +1672,7 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode)
// Check that node exists
if (!p->Openflag) return 102;
if (index <= 0 || index > net->Nnodes) return 204;
if (index <= 0 || index > net->Nnodes) return 203;
if (actionCode < EN_UNCONDITIONAL || actionCode > EN_CONDITIONAL) return 251;
// Can't delete a water quality trace node
@@ -1930,7 +1946,7 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
break;
case EN_TANKLEVEL:
if (index <= nJuncs) return 251;
if (index <= nJuncs) return 0;
v = (Tank[index - nJuncs].H0 - Node[index].El) * Ucf[ELEV];
break;
@@ -2018,7 +2034,7 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
break;
case EN_TANKVOLUME:
if (index <= nJuncs) return 251;
if (index <= nJuncs) return 0;
v = tankvolume(p, index - nJuncs, NodeHead[index]) * Ucf[VOLUME];
break;
@@ -2103,14 +2119,14 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
break;
case EN_EMITTER:
if (index > nJuncs) return 203;
if (value < 0.0) return 202;
if (index > nJuncs) return 0;
if (value < 0.0) return 209;
if (value > 0.0) value = pow((Ucf[FLOW] / value), hyd->Qexp) / Ucf[PRESSURE];
Node[index].Ke = value;
break;
case EN_INITQUAL:
if (value < 0.0) return 202;
if (value < 0.0) return 209;
Node[index].C0 = value / Ucf[QUALITY];
if (index > nJuncs) Tank[index - nJuncs].C = Node[index].C0;
break;
@@ -2118,7 +2134,7 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
case EN_SOURCEQUAL:
case EN_SOURCETYPE:
case EN_SOURCEPAT:
if (value < 0.0) return 202;
if (value < 0.0) return 209;
source = Node[index].S;
if (source == NULL)
{
@@ -2142,10 +2158,10 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
if (j < CONCEN || j > FLOWPACED) return 251;
else source->Type = (char)j;
}
return 0;
break;
case EN_TANKLEVEL:
if (index <= nJuncs) return 251;
if (index <= nJuncs) return 0;
j = index - nJuncs;
if (Tank[j].A == 0.0) /* Tank is a reservoir */
{
@@ -2158,7 +2174,7 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
else
{
value = Node[index].El + value / Ucf[ELEV];
if (value > Tank[j].Hmax || value < Tank[j].Hmin) return 202;
if (value > Tank[j].Hmax || value < Tank[j].Hmin) return 209;
Tank[j].H0 = value;
Tank[j].V0 = tankvolume(p, j, Tank[j].H0);
// Resetting Volume in addition to initial volume
@@ -2168,10 +2184,10 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
break;
case EN_TANKDIAM:
if (value <= 0.0) return 202;
if (index <= nJuncs) return 251;
if (value <= 0.0) return 209;
if (index <= nJuncs) return 0;
j = index - nJuncs;
if (j > 0 && Tank[j].A > 0.0)
if (Tank[j].A > 0.0)
{
value /= Ucf[ELEV];
Tank[j].A = PI * SQR(value) / 4.0;
@@ -2179,82 +2195,78 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
Tank[j].V0 = tankvolume(p, j, Tank[j].H0);
Tank[j].Vmax = tankvolume(p, j, Tank[j].Hmax);
}
else return 251;
break;
case EN_MINVOLUME:
if (value < 0.0) return 202;
if (index <= nJuncs) return 251;
if (value < 0.0) return 209;
if (index <= nJuncs) return 0;
j = index - nJuncs;
if (j > 0 && Tank[j].A > 0.0)
if (Tank[j].A > 0.0)
{
Tank[j].Vmin = value / Ucf[VOLUME];
Tank[j].V0 = tankvolume(p, j, Tank[j].H0);
Tank[j].Vmax = tankvolume(p, j, Tank[j].Hmax);
}
else return 251;
break;
case EN_MINLEVEL:
if (value < 0.0) return 202;
if (index <= nJuncs) return 251; // not a tank or reservoir
if (value < 0.0) return 209;
if (index <= nJuncs) return 0; // not a tank or reservoir
j = index - nJuncs;
if (Tank[j].A == 0.0) return 251; // node is a reservoir
if (Tank[j].A == 0.0) return 0; // node is a reservoir
hTmp = value / Ucf[ELEV] + Node[index].El;
if (hTmp < Tank[j].Hmax && hTmp <= Tank[j].H0)
{
if (Tank[j].Vcurve > 0) return 202;
if (Tank[j].Vcurve > 0) return 0;
Tank[j].Hmin = hTmp;
Tank[j].Vmin = (Tank[j].Hmin - Node[index].El) * Tank[j].A;
}
else return 251;
else return 209;
break;
case EN_MAXLEVEL:
if (value < 0.0) return 202;
if (index <= nJuncs) return 251; // not a tank or reservoir
if (value < 0.0) return 209;
if (index <= nJuncs) return 0; // not a tank or reservoir
j = index - nJuncs;
if (Tank[j].A == 0.0) return 251; // node is a reservoir
if (Tank[j].A == 0.0) return 0; // node is a reservoir
hTmp = value / Ucf[ELEV] + Node[index].El;
if (hTmp > Tank[j].Hmin && hTmp >= Tank[j].H0)
{
if (Tank[j].Vcurve > 0) return 202;
if (Tank[j].Vcurve > 0) return 0;
Tank[j].Hmax = hTmp;
Tank[j].Vmax = tankvolume(p, j, Tank[j].Hmax);
}
else return 251;
else return 209;
break;
case EN_MIXMODEL:
j = ROUND(value);
if (index <= nJuncs) return 251;
if (j < MIX1 || j > LIFO) return 202;
if (index > nJuncs && Tank[index - nJuncs].A > 0.0)
if (index <= nJuncs) return 0;
if (j < MIX1 || j > LIFO) return 251;
if (Tank[index - nJuncs].A > 0.0)
{
Tank[index - nJuncs].MixModel = (char)j;
}
else return 251;
break;
case EN_MIXFRACTION:
if (value < 0.0 || value > 1.0) return 202;
if (index <= nJuncs) return 251;
if (index <= nJuncs) return 0;
if (value < 0.0 || value > 1.0) return 209;
j = index - nJuncs;
if (j > 0 && Tank[j].A > 0.0)
if (Tank[j].A > 0.0)
{
Tank[j].V1max = value * Tank[j].Vmax;
}
break;
case EN_TANK_KBULK:
if (index <= nJuncs) return 251;
if (index <= nJuncs) return 0;
j = index - nJuncs;
if (j > 0 && Tank[j].A > 0.0)
if (Tank[j].A > 0.0)
{
Tank[j].Kb = value / SECperDAY;
qual->Reactflag = 1;
}
else return 251;
break;
default:
@@ -2280,7 +2292,7 @@ int DLLEXPORT EN_getcoord(EN_Project p, int index, EN_API_FLOAT_TYPE *x,
if (!p->Openflag) return 102;
if (index < 1 || index > p->network.Nnodes) return 203;
// check if node have coords
// check if node has coords
node = &net->Node[index];
if (node->X == MISSING ||
node->Y == MISSING) return 254;
@@ -2353,7 +2365,7 @@ int DLLEXPORT EN_setdemandmodel(EN_Project p, int type, EN_API_FLOAT_TYPE pmin,
*/
{
if (type < 0 || type > EN_PDA) return 251;
if (pmin > preq || pexp <= 0.0) return 202;
if (pmin > preq || pexp <= 0.0) return 209;
p->hydraul.DemandModel = type;
p->hydraul.Pmin = pmin / p->Ucf[PRESSURE];
p->hydraul.Preq = preq / p->Ucf[PRESSURE];
@@ -2958,6 +2970,9 @@ int DLLEXPORT EN_setlinknodes(EN_Project p, int index, int node1, int node2)
if (node1 < 0 || node1 > net->Nnodes) return 203;
if (node2 < 0 || node2 > net->Nnodes) return 203;
// Check that nodes are not the same
if (node1 == node2) return 222;
// Check for illegal valve connection
type = net->Link[index].Type;
if (type == EN_PRV || type == EN_PSV || type == EN_FCV)
@@ -2991,7 +3006,6 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, EN_LinkProperty code,
Hydraul *hyd = &p->hydraul;
double a, h, q, v = 0.0;
int returnValue = 0;
int pmp;
Slink *Link = net->Link;
Spump *Pump = net->Pump;
@@ -3184,12 +3198,6 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, EN_LinkProperty code,
if (Link[index].Type == EN_PUMP)
{
v = (double)Pump[findpump(&p->network, index)].Hcurve;
if (v == 0) returnValue = 226;
}
else
{
v = 0;
returnValue = 211;
}
break;
@@ -3197,20 +3205,14 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, EN_LinkProperty code,
if (Link[index].Type == EN_PUMP)
{
v = (double)Pump[findpump(&p->network, index)].Ecurve;
if (v == 0) returnValue = 268;
}
else
{
v = 0;
returnValue = 211;
}
break;
default:
v = 0;
returnValue = 251;
return 251;
}
*value = (EN_API_FLOAT_TYPE)v;
return returnValue;
return 0;
}
int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int code, EN_API_FLOAT_TYPE v)
@@ -3241,7 +3243,7 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
case EN_DIAMETER:
if (Link[index].Type != EN_PUMP)
{
if (value <= 0.0) return 202;
if (value <= 0.0) return 211;
value /= Ucf[DIAM]; // Convert to feet
r = Link[index].Diam / value; // Ratio of old to new diam
Link[index].Km *= SQR(r) * SQR(r); // Adjust minor loss factor
@@ -3253,7 +3255,7 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
case EN_LENGTH:
if (Link[index].Type <= EN_PIPE)
{
if (value <= 0.0) return 202;
if (value <= 0.0) return 211;
Link[index].Len = value / Ucf[ELEV];
resistcoeff(p, index);
}
@@ -3262,7 +3264,7 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
case EN_ROUGHNESS:
if (Link[index].Type <= EN_PIPE)
{
if (value <= 0.0) return 202;
if (value <= 0.0) return 211;
Link[index].Kc = value;
if (hyd->Formflag == DW) Link[index].Kc /= (1000.0 * Ucf[ELEV]);
resistcoeff(p, index);
@@ -3272,7 +3274,7 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
case EN_MINORLOSS:
if (Link[index].Type != EN_PUMP)
{
if (value <= 0.0) return 202;
if (value <= 0.0) return 211;
Link[index].Km = 0.02517 * value / SQR(Link[index].Diam) /
SQR(Link[index].Diam);
}
@@ -3283,7 +3285,7 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
// Cannot set status for a check valve
if (Link[index].Type == EN_CVPIPE) return 207;
s = (char)ROUND(value);
if (s < 0 || s > 1) return 251;
if (s < 0 || s > 1) return 211;
if (code == EN_INITSTATUS)
{
setlinkstatus(p, index, s, &Link[index].Status, &Link[index].Kc);
@@ -3296,7 +3298,7 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
case EN_INITSETTING:
case EN_SETTING:
if (value < 0.0) return 202;
if (value < 0.0) return 211;
if (Link[index].Type == EN_PIPE || Link[index].Type == EN_CVPIPE)
{
return EN_setlinkvalue(p, index, EN_ROUGHNESS, v);
@@ -3318,9 +3320,9 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
case EN_TCV:
break;
case EN_GPV:
return 202; // Cannot modify setting for GPV
return 207; // Cannot modify setting for GPV
default:
return 251;
return 0;
}
if (code == EN_INITSETTING)
{
@@ -3379,7 +3381,8 @@ int DLLEXPORT EN_getpumptype(EN_Project p, int index, int *type)
*type = -1;
if (!p->Openflag) return 102;
if (index < 1 || index > Nlinks || EN_PUMP != Link[index].Type) return 204;
if (index < 1 || index > Nlinks) return 204;
if (EN_PUMP != Link[index].Type) return 216;
*type = Pump[findpump(&p->network, index)].Ptype;
return 0;
}
@@ -3399,8 +3402,10 @@ int DLLEXPORT EN_getheadcurveindex(EN_Project p, int index, int *curveindex)
Spump *Pump = net->Pump;
const int Nlinks = net->Nlinks;
*curveindex = 0;
if (!p->Openflag) return 102;
if (index < 1 || index > Nlinks || EN_PUMP != Link[index].Type) return 204;
if (index < 1 || index > Nlinks) return 204;
if (EN_PUMP != Link[index].Type) return 216;
*curveindex = Pump[findpump(net, index)].Hcurve;
return 0;
}
@@ -3426,7 +3431,8 @@ int DLLEXPORT EN_setheadcurveindex(EN_Project p, int index, int curveindex)
// Check for valid parameters
if (!p->Openflag) return 102;
if (index < 1 || index > net->Nlinks || EN_PUMP != net->Link[index].Type) return 204;
if (index < 1 || index > net->Nlinks) return 204;
if (EN_PUMP != net->Link[index].Type) return 0;
if (curveindex <= 0 || curveindex > net->Ncurves) return 206;
// Assign the new curve to the pump
@@ -3649,7 +3655,7 @@ int DLLEXPORT EN_setpattern(EN_Project p, int index, EN_API_FLOAT_TYPE *f, int n
// Check for valid arguments
if (!p->Openflag) return 102;
if (index <= 0 || index > net->Npats) return 205;
if (n <= 0) return 202;
if (n <= 0) return 251;
// Re-set number of time periods & reallocate memory for multipliers
Pattern[index].Length = n;
@@ -3893,6 +3899,9 @@ int DLLEXPORT EN_setcurve(EN_Project p, int index, EN_API_FLOAT_TYPE *x,
if (index <= 0 || index > net->Ncurves) return 206;
if (n <= 0) return 202;
// Check that x values are increasing
for (j = 1; j < n; j++) if (x[j-1] >= x[j]) return 230;
// Re-set number of points & reallocate memory for values
curve = &net->Curve[index];
curve->Npts = n;

View File

@@ -1,76 +1,71 @@
//EPANET 2 Error Messages
DAT(0,"ok")
DAT(101,"insufficient memory available")
DAT(102,"no network data available")
DAT(103,"hydraulic solver not opened")
DAT(104,"no hydraulics for water quality analysis")
DAT(105,"water quality solver not opened")
DAT(106,"no results saved to report on")
DAT(107,"hydraulics supplied from external file")
DAT(108,"cannot use external file while hydraulics solver is active")
DAT(109,"cannot change time parameter when solver is active")
DAT(110,"cannot solve network hydraulic equations")
DAT(120,"cannot solve water quality transport equations")
DAT(0,EN_OK,"ok")
DAT(101,ENERR_INSUF_MEM,"insufficient memory available")
DAT(102,ENERR_NO_NET_DATA,"no network data available")
DAT(103,ENERR_HYD_NOT_INIT,"hydraulics not initialized")
DAT(104,ENERR_NO_HYD,"no hydraulics for water quality analysis")
DAT(105,ENERR_WQ_NOT_INIT,"water quality not initialized")
DAT(106,ENERR_NO_RESULT,"no results saved to report on")
DAT(107,ENERR_HYD_EXT_FILE,"hydraulics supplied from external file")
DAT(108,ENERR_CANT_USE_EXT_FILE,"cannot use external file while hydraulics solver is active")
DAT(109,ENERR_CANT_CHANGE_TIME_PARAM,"cannot change time parameter when solver is active")
DAT(110,ENERR_CANT_SOLVE_HYD,"cannot solve network hydraulic equations")
DAT(120,ENERR_CANT_SOLVE_WQ,"cannot solve water quality transport equations")
// These errors apply only to an input file
DAT(200,"one or more errors in input file")
DAT(201,"syntax error")
DAT(200,ENERR_INP_ERR,"one or more errors in input file")
DAT(201,ENERR_SYNTAX_LINE,"syntax error in following line of section")
DAT(202,ENERR_ILLEGAL_NUM,"function call contains illegal numeric value")
DAT(203,ENERR_UNDEF_NODE,"function call refers to undefined node")
DAT(204,ENERR_UNDEF_LINK,"function call refers to undefined link")
DAT(205,ENERR_UNDEF_PAT,"function call refers to undefined time pattern")
DAT(206,ENERR_UNDEF_CURVE,"function call refers to undefined curve")
DAT(207,ENERR_CANT_CONTROL_CV,"function call attempts to control a CV")
// These errors apply to both an input file and to API functions
DAT(202,"illegal numeric value")
DAT(203,"undefined node")
DAT(204,"undefined link")
DAT(205,"undefined time pattern")
DAT(206,"undefined curve")
DAT(207,"attempt to control CV/GPV link")
DAT(208,"reference to undefined node")
DAT(209,"illegal node property value")
DAT(210,"reference to undefined link")
DAT(211,"illegal link property value")
DAT(212,"undefined trace node")
DAT(213,"invalid option value")
DAT(214,"too many characters in input line")
DAT(215,"duplicate ID label")
DAT(216,"reference to undefined pump")
DAT(217,"invalid pump energy data")
DAT(219,"illegal valve connection to tank node")
DAT(220,"illegal valve connection to another valve")
DAT(221,"mis-placed rule clause in rule-based control")
DAT(222,"same start and end nodes for link")
DAT(208,ENERR_SPEC_UNDEF_NODE,"undefined Node")
DAT(209,ENERR_ILLEGAL_VAL_NODE,"illegal value for Node")
DAT(210,ENERR_SPEC_UNDEF_LINK,"specified for undefined Link")
DAT(211,ENERR_ILLEGAL_VAL_LINK,"illegal value for Link")
DAT(212,ENERR_TRACE_NODE,"invalid trace node")
DAT(213,ENERR_ILLEGAL_OPT,"illegal option value in section")
DAT(214,ENERR_TOO_MANY_CHAR,"following line of section contains too many characters")
DAT(215,ENERR_DUPLICATE_ID,"duplicate ID")
DAT(216,ENERR_UNDEF_PUMP,"data specified for undefined Pump")
DAT(217,ENERR_INVALID_DATA_PUMP,"invalid data for Pump")
DAT(219,ENERR_ILLEGAL_CON_TANK,"illegally connected to a tank")
DAT(220,ENERR_ILLEGAL_CON_VALVE,"illegally connected to another valve")
DAT(221,ENERR_RULE_CLAUSE, "mis-placed rule clause")
DAT(222,ENERR_SAME_START_END,"same start and end nodes")
DAT(223,ENERR_NOT_ENOUGH_NODES,"not enough nodes in network")
DAT(224,ENERR_NO_TANKS_RES,"no tanks or reservoirs in network")
DAT(225,ENERR_INVALID_LEVELS,"invalid lower/upper levels for Tank")
DAT(226,ENERR_NO_HEAD_CURVE,"no head curve supplied for Pump")
DAT(227,ENERR_INVALID_HEAD_CURVE,"invalid head curve for Pump")
DAT(230,ENERR_X_NONINCREASING,"Curve has nonincreasing x-values")
DAT(233,ENERR_NODE_UNCONNECTED,"Node is unconnected")
DAT(240,ENERR_UNDEF_SOURCE,"undefined source")
DAT(241,ENERR_UNDEF_CONTROL,"refers to undefined control")
DAT(250,ENERR_INVALID_FORMAT,"function call contains invalid format")
DAT(251,ENERR_INVALID_CODE,"function call contains invalid parameter code")
DAT(253,ENERR_NO_DEMAND_CAT,"function applied to nonexistent demand category")
DAT(254,ENERR_NO_COORDS,"function applied to node with no coordinates")
DAT(255,ENERR_COORDS_NOT_LOADED,"function fails because no node coordinates were supplied")
DAT(257,ENERR_NO_RULE,"function applied to nonexistent rule")
DAT(258,ENERR_NO_CONDITION_ACTION,"function applied to nonexistent rule clause")
DAT(260,ENERR_DEL_TRACE_NODE,"cannot delete node assigned as a Trace Node")
DAT(261,ENERR_DEL_NODE_LINK, "cannot delete a node or link contained in a control")
DAT(301,ENERR_FILES_ARE_SAME,"identical file names")
DAT(302,ENERR_CANT_OPEN_INP,"cannot open input file")
DAT(303,ENERR_CANT_OPEN_RPT,"cannot open report file")
DAT(304,ENERR_CANT_OPEN_BIN,"cannot open binary output file")
DAT(305,ENERR_CANT_OPEN_HYD,"cannot open hydraulics file")
DAT(306,ENERR_HYD_FILE_NOMATCH,"hydraulics file does not match network data")
DAT(307,ENERR_CANT_READ_HYD,"cannot read hydraulics file")
DAT(308,ENERR_CANT_SAVE_RES,"cannot save results to file")
DAT(309,ENERR_CANT_SAVE_RPT,"cannot save results to report file")
DAT(411,ENERR_NO_MEM_ALLOC,"no memory allocated for results")
DAT(412,ENERR_NO_RESULTS_NO_FILE,"no results; binary file hasn't been opened")
DAT(435,ENERR_RUN_TERMINATED,"run terminated; no results in binary file")
// These errors apply to network consistency check
DAT(223,"not enough nodes in network")
DAT(224,"no tanks or reservoirs in network")
DAT(225,"invalid lower/upper levels for tank")
DAT(226,"no head curve or power rating for pump")
DAT(227,"invalid head curve for pump")
DAT(230,"nonincreasing x-values for curve")
DAT(233,"network has unconnected node")
// These errors apply only to API functions
DAT(240,"nonexistent source")
DAT(241,"nonexistent control")
DAT(250,"invalid format")
DAT(251,"invalid parameter code")
DAT(253,"nonexistent demand category")
DAT(254,"node with no coordinates")
DAT(257,"nonexistent rule")
DAT(258,"nonexistent rule clause")
DAT(260,"attempt to delete node assigned as a Trace Node")
DAT(261,"attempt to delete a node or link contained in a control")
// File errors
DAT(301,"identical file names")
DAT(302,"cannot open input file")
DAT(303,"cannot open report file")
DAT(304,"cannot open binary output file")
DAT(305,"cannot open hydraulics file")
DAT(306,"hydraulics file does not match network data")
DAT(307,"cannot read hydraulics file")
DAT(308,"cannot save results to file")
DAT(309,"cannot save results to report file")

View File

@@ -7,7 +7,7 @@ Description: retrieves network data from an EPANET input file
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 11/10/2018
Last Updated: 12/15/2018
******************************************************************************
*/
@@ -357,6 +357,7 @@ int inittanks(Project *pr)
int i, j, n = 0;
double a;
int errcode = 0, levelerr;
char errmsg[MAXMSG+1] = "";
Stank *tank;
Scurve *curve;
@@ -383,14 +384,6 @@ int inittanks(Project *pr)
levelerr = 1;
}
// Report error in levels if found
if (levelerr)
{
sprintf(pr->Msg, "%s node: %s", geterrmsg(225, pr->Msg),
net->Node[tank->Node].ID);
writeline(pr, pr->Msg);
errcode = 200;
}
else
{
// Find min., max., and initial volumes from curve
@@ -403,6 +396,15 @@ int inittanks(Project *pr)
tank->A = sqrt(4.0 * a / PI);
}
}
// Report error in levels if found
if (levelerr)
{
sprintf(pr->Msg, "Error 225: %s node %s", geterrmsg(225, errmsg),
net->Node[tank->Node].ID);
writeline(pr, pr->Msg);
errcode = 200;
}
}
return errcode;
}

View File

@@ -7,7 +7,7 @@ Description: reads and interprets network data from an EPANET input file
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 11/10/2018
Last Updated: 12/15/2018
******************************************************************************
*/
@@ -179,6 +179,7 @@ int readdata(Project *pr)
parser->Comment);
// Skip blank lines and comments
parser->ErrTok = -1;
if (parser->Ntokens == 0) continue;
if (*parser->Tok[0] == ';') continue;
@@ -218,7 +219,7 @@ int readdata(Project *pr)
inperr = newline(pr, sect, line);
if (inperr > 0)
{
inperrmsg(pr,inperr, sect, line);
inperrmsg(pr, inperr, sect, line);
errsum++;
}
}
@@ -327,6 +328,7 @@ int getpumpparams(Project *pr)
{
Network *net = &pr->network;
int i, k, errcode = 0;
char errmsg[MAXMSG+1];
for (i = 1; i <= net->Npumps; i++)
{
@@ -334,8 +336,8 @@ int getpumpparams(Project *pr)
if (errcode)
{
k = net->Pump[i].Link;
sprintf(pr->Msg, "%s link: %s", geterrmsg(errcode, pr->Msg),
net->Link[k].ID);
sprintf(pr->Msg, "Error %d: %s %s",
errcode, geterrmsg(errcode, errmsg), net->Link[k].ID);
writeline(pr, pr->Msg);
return 200;
}
@@ -596,8 +598,7 @@ int unlinked(Project *pr)
if (marked[i] == 0)
{
err++;
sprintf(pr->Msg, "%s link: %s", geterrmsg(233, pr->Msg),
net->Node[i].ID);
sprintf(pr->Msg, "Error 233: %s %s", geterrmsg(233, pr->Msg), net->Node[i].ID);
writeline(pr, pr->Msg);
}
if (err >= MAXERRS) break;
@@ -685,6 +686,7 @@ int getcurves(Project *pr)
int i, j;
double x;
char errmsg[MAXMSG+1];
SFloatlist *fx, *fy;
STmplist *tmpcurve;
Scurve *curve;
@@ -705,10 +707,9 @@ int getcurves(Project *pr)
// Check that network curve has data points
if (curve->Npts <= 0)
{
sprintf(pr->Msg, "%s link: %s", geterrmsg(230, pr->Msg),
curve->ID);
sprintf(pr->Msg, "Error 230: %s %s", geterrmsg(230, errmsg), curve->ID);
writeline(pr, pr->Msg);
return (200);
return 200;
}
// Allocate memory for network's curve data
@@ -726,10 +727,9 @@ int getcurves(Project *pr)
// Check that x data is in ascending order
if (fx->value >= x)
{
sprintf(pr->Msg, "%s link: %s", geterrmsg(230, pr->Msg),
curve->ID);
sprintf(pr->Msg, "Error 230: %s %s", geterrmsg(230, errmsg), curve->ID);
writeline(pr, pr->Msg);
return (200);
return 200;
}
x = fx->value;
@@ -967,33 +967,18 @@ void inperrmsg(Project *pr, int err, int sect, char *line)
{
Parser *parser = &pr->parser;
char errStr[MAXMSG + 1];
char id[MAXMSG + 1];
char errStr[MAXMSG + 1] = "";
char tok[MAXMSG + 1];
// get text for error message
sprintf(pr->Msg, "%s - section: %s", geterrmsg(err, errStr), SectTxt[sect]);
// Get token associated with input error
if (parser->ErrTok >= 0) strcpy(tok, parser->Tok[parser->ErrTok]);
else strcpy(tok, "");
// Retrieve ID label of object with input error
// (No ID used for CONTROLS or REPORT sections)
switch (sect)
{
case _CONTROLS:
case _REPORT:
// don't append
break;
case _ENERGY:
sprintf(id, " id: %s", parser->Tok[1]);
break;
default:
sprintf(id, " id: %s", parser->Tok[0]);
break;
}
strcat(pr->Msg, id);
// write error message to report file
sprintf(pr->Msg, "Error %d: %s %s in %s section:",
err, geterrmsg(err, errStr), tok, SectTxt[sect]);
writeline(pr, pr->Msg);
// Echo input line for syntax errors, and
// errors in CONTROLS and OPTIONS sections
if (sect == _CONTROLS || err == 201 || err == 213) writeline(pr, line);
else writeline(pr, "");
// Echo input line
writeline(pr, line);
}

View File

@@ -7,7 +7,7 @@ Description: parses network data from a line of an EPANET input file
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 11/10/2018
Last Updated: 12/15/2018
******************************************************************************
*/
@@ -43,8 +43,24 @@ static int optionchoice(Project *, int);
static int optionvalue(Project *, int);
static int getpumpcurve(Project *, int);
static void changestatus(Network *, int, StatusType, double);
static int setError(Parser *, int, int);
int setError(Parser *parser, int tokindex, int errcode)
/*
**--------------------------------------------------------------
** Input: tokindex = index of input line token
** errcode = an error code
** Output: returns error code
** Purpose: records index of token from line of input associated
** with an error
**--------------------------------------------------------------
*/
{
parser->ErrTok = tokindex;
return errcode;
}
int juncdata(Project *pr)
/*
**--------------------------------------------------------------
@@ -76,16 +92,16 @@ int juncdata(Project *pr)
net->Njuncs++;
net->Nnodes++;
njuncs = net->Njuncs;
if (!addnodeID(net, net->Njuncs, parser->Tok[0])) return 215;
if (!addnodeID(net, net->Njuncs, parser->Tok[0])) return setError(parser, 0, 215);
// Check for valid data
if (n < 2) return 201;
if (!getfloat(parser->Tok[1], &el)) return 202;
if (n >= 3 && !getfloat(parser->Tok[2], &y)) return 202;
if (!getfloat(parser->Tok[1], &el)) return setError(parser, 1, 202);
if (n >= 3 && !getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
if (n >= 4)
{
patlist = getlistitem(parser->Tok[3], parser->Patlist);
if (patlist == NULL) return 205;
if (patlist == NULL) return setError(parser, 3, 205);
p = patlist->i;
}
@@ -155,11 +171,11 @@ int tankdata(Project *pr)
net->Nnodes++;
i = parser->MaxJuncs + net->Ntanks;
if (!addnodeID(net, i, parser->Tok[0])) return 215;
if (!addnodeID(net, i, parser->Tok[0])) return setError(parser, 0, 215);
// Check for valid data
if (n < 2) return (201);
if (!getfloat(parser->Tok[1], &el)) return 202;
if (n < 2) return 201;
if (!getfloat(parser->Tok[1], &el)) return setError(parser, 1, 202);
// Tank is reservoir
if (n <= 3)
@@ -168,7 +184,7 @@ int tankdata(Project *pr)
if (n == 3)
{
tmplist = getlistitem(parser->Tok[2], parser->Patlist);
if (tmplist == NULL) return 205;
if (tmplist == NULL) return setError(parser, 2, 205);
pattern = tmplist->i;
}
}
@@ -177,21 +193,25 @@ int tankdata(Project *pr)
// Tank is a storage tank
else
{
if (!getfloat(parser->Tok[2], &initlevel)) return 202;
if (!getfloat(parser->Tok[3], &minlevel)) return 202;
if (!getfloat(parser->Tok[4], &maxlevel)) return 202;
if (!getfloat(parser->Tok[5], &diam)) return 202;
if (diam < 0.0) return 202;
if (n >= 7 && !getfloat(parser->Tok[6], &minvol)) return 202;
if (!getfloat(parser->Tok[2], &initlevel)) return setError(parser, 2, 202);
if (!getfloat(parser->Tok[3], &minlevel)) return setError(parser, 3, 202);
if (!getfloat(parser->Tok[4], &maxlevel)) return setError(parser, 4, 202);
if (!getfloat(parser->Tok[5], &diam)) return setError(parser, 5, 202);
if (n >= 7 && !getfloat(parser->Tok[6], &minvol)) return setError(parser, 6, 202);
// If volume curve supplied check it exists
if (n == 8)
{
tmplist = getlistitem(parser->Tok[7], parser->Curvelist);
if (tmplist == NULL) return 202;
if (tmplist == NULL) return setError(parser, 7, 206);
curve = tmplist->i;
net->Curve[curve].Type = V_CURVE;
}
if (initlevel < 0.0) return setError(parser, 2, 209);
if (minlevel < 0.0) return setError(parser, 3, 209);
if (maxlevel < 0.0) return setError(parser, 4, 209);
if (diam < 0.0) return setError(parser, 5, 209);
if (minvol < 0.0) return setError(parser, 6, 209);
}
node = &net->Node[i];
tank = &net->Tank[net->Ntanks];
@@ -261,18 +281,20 @@ int pipedata(Project *pr)
if (net->Nlinks == parser->MaxLinks) return 200;
net->Npipes++;
net->Nlinks++;
if (!addlinkID(net, net->Nlinks, parser->Tok[0])) return 215;
if (!addlinkID(net, net->Nlinks, parser->Tok[0])) return setError(parser, 0, 215);
// Check for valid data
if (n < 6) return 201;
if ((j1 = findnode(net, parser->Tok[1])) == 0 ||
(j2 = findnode(net, parser->Tok[2])) == 0) return 203;
if (j1 == j2) return 222;
if ((j1 = findnode(net, parser->Tok[1])) == 0) return setError(parser, 1, 203);
if ((j2 = findnode(net, parser->Tok[2])) == 0) return setError(parser, 2, 203);
if (j1 == j2) return setError(parser, 0, 222);
if (!getfloat(parser->Tok[3], &length) ||
!getfloat(parser->Tok[4], &diam) ||
!getfloat(parser->Tok[5], &rcoeff)) return 202;
if (length <= 0.0 || diam <= 0.0 || rcoeff <= 0.0) return 202;
if (!getfloat(parser->Tok[3], &length)) return setError(parser, 3, 202);
if (length <= 0.0) return setError(parser, 3, 211);
if (!getfloat(parser->Tok[4], &diam)) return setError(parser, 4, 202);
if (diam <= 0.0) return setError(parser, 4, 211);
if (!getfloat(parser->Tok[5], &rcoeff)) return setError(parser, 5, 202);
if (rcoeff <= 0.0) setError(parser, 5, 211);
// Either a loss coeff. or a status is supplied
if (n == 7)
@@ -280,19 +302,19 @@ int pipedata(Project *pr)
if (match(parser->Tok[6], w_CV)) type = CVPIPE;
else if (match(parser->Tok[6], w_CLOSED)) status = CLOSED;
else if (match(parser->Tok[6], w_OPEN)) status = OPEN;
else if (!getfloat(parser->Tok[6], &lcoeff)) return (202);
else if (!getfloat(parser->Tok[6], &lcoeff)) return setError(parser, 6, 202);
}
// Both a loss coeff. and a status is supplied
if (n == 8)
{
if (!getfloat(parser->Tok[6], &lcoeff)) return 202;
if (!getfloat(parser->Tok[6], &lcoeff)) return setError(parser, 6, 202);
if (match(parser->Tok[7], w_CV)) type = CVPIPE;
else if (match(parser->Tok[7], w_CLOSED)) status = CLOSED;
else if (match(parser->Tok[7], w_OPEN)) status = OPEN;
else return 202;
else return setError(parser, 7, 213);
}
if (lcoeff < 0.0) return 202;
if (lcoeff < 0.0) return setError(parser, 6, 211);
// Save pipe data
link = &net->Link[net->Nlinks];
@@ -347,13 +369,13 @@ int pumpdata(Project *pr)
net->Npumps == parser->MaxPumps) return 200;
net->Nlinks++;
net->Npumps++;
if (!addlinkID(net, net->Nlinks, parser->Tok[0])) return 215;
if (!addlinkID(net, net->Nlinks, parser->Tok[0])) return setError(parser, 0, 215);
// Check for valid data
if (n < 4) return 201;
if ((j1 = findnode(net, parser->Tok[1])) == 0 ||
(j2 = findnode(net, parser->Tok[2])) == 0) return 203;
if (j1 == j2) return 222;
if (n < 3) return 201;
if ((j1 = findnode(net, parser->Tok[1])) == 0) return setError(parser, 1, 203);
if ((j2 = findnode(net, parser->Tok[2])) == 0) return setError(parser, 2, 203);
if (j1 == j2) return setError(parser, 0, 222);
// Save pump data
link = &net->Link[net->Nlinks];
@@ -378,6 +400,7 @@ int pumpdata(Project *pr)
pump->Upat = 0;
pump->Ecost = 0.0;
pump->Epat = 0;
if (n < 4) return 0;
// If 4-th token is a number then input follows Version 1.x format
// so retrieve pump curve parameters
@@ -386,10 +409,10 @@ int pumpdata(Project *pr)
m = 1;
for (j = 4; j < n; j++)
{
if (!getfloat(parser->Tok[j], &parser->X[m])) return 202;
if (!getfloat(parser->Tok[j], &parser->X[m])) return setError(parser, j, 202);
m++;
}
return (getpumpcurve(pr,m));
return (getpumpcurve(pr, m));
}
// Otherwise input follows Version 2 format
@@ -400,26 +423,26 @@ int pumpdata(Project *pr)
if (match(parser->Tok[m - 1], w_POWER)) // Const. HP curve
{
y = atof(parser->Tok[m]);
if (y <= 0.0) return (202);
if (y <= 0.0) return setError(parser, m, 202);
pump->Ptype = CONST_HP;
link->Km = y;
}
else if (match(parser->Tok[m - 1], w_HEAD)) // Custom pump curve
{
tmplist = getlistitem(parser->Tok[m], parser->Curvelist);
if (tmplist == NULL) return 206;
if (tmplist == NULL) return setError(parser, m, 206);
pump->Hcurve = tmplist->i;
}
else if (match(parser->Tok[m - 1], w_PATTERN)) // Speed/status pattern
{
tmplist = getlistitem(parser->Tok[m], parser->Patlist);
if (tmplist == NULL) return 205;
if (tmplist == NULL) return setError(parser, m, 205);
pump->Upat = tmplist->i;
}
else if (match(parser->Tok[m - 1], w_SPEED)) // Speed setting
{
if (!getfloat(parser->Tok[m], &y)) return 202;
if (y < 0.0) return 202;
if (!getfloat(parser->Tok[m], &y)) return setError(parser, m, 202);
if (y < 0.0) return setError(parser, m, 211);
link->Kc = y;
}
else return 201;
@@ -460,13 +483,13 @@ int valvedata(Project *pr)
net->Nvalves == parser->MaxValves) return 200;
net->Nvalves++;
net->Nlinks++;
if (!addlinkID(net, net->Nlinks, parser->Tok[0])) return 215;
if (!addlinkID(net, net->Nlinks, parser->Tok[0])) return setError(parser, 0, 215);
// Check for valid data
if (n < 6) return 201;
if ((j1 = findnode(net, parser->Tok[1])) == 0 ||
(j2 = findnode(net, parser->Tok[2])) == 0) return (203);
if (j1 == j2) return 222;
if ((j1 = findnode(net, parser->Tok[1])) == 0) return setError(parser, 1, 203);
if ((j2 = findnode(net, parser->Tok[2])) == 0) return setError(parser, 2, 203);
if (j1 == j2) return setError(parser, 0, 222);
if (match(parser->Tok[4], w_PRV)) type = PRV;
else if (match(parser->Tok[4], w_PSV)) type = PSV;
@@ -474,28 +497,31 @@ int valvedata(Project *pr)
else if (match(parser->Tok[4], w_FCV)) type = FCV;
else if (match(parser->Tok[4], w_TCV)) type = TCV;
else if (match(parser->Tok[4], w_GPV)) type = GPV;
else return 201;
else return setError(parser, 4, 213);
if (!getfloat(parser->Tok[3], &diam)) return 202;
if (diam <= 0.0) return 202;
if (!getfloat(parser->Tok[3], &diam)) return setError(parser, 3, 202); 202;
if (diam <= 0.0) return setError(parser, 3, 211);
// Find headloss curve for GPV
if (type == GPV)
{
tmplist = getlistitem(parser->Tok[5], parser->Curvelist);
if (tmplist == NULL) return 206;
if (tmplist == NULL) return setError(parser, 5, 206);
setting = tmplist->i;
net->Curve[tmplist->i].Type = H_CURVE;
status = OPEN;
}
else if (!getfloat(parser->Tok[5], &setting)) return 202;
if (n >= 7 && !getfloat(parser->Tok[6], &lcoeff)) return 202;
else if (!getfloat(parser->Tok[5], &setting)) return setError(parser, 5, 202);
if (n >= 7 && !getfloat(parser->Tok[6], &lcoeff)) return setError(parser, 6, 202);
// Check that PRV, PSV, or FCV not connected to a tank &
// check for illegal connections between pairs of valves
if ((j1 > net->Njuncs || j2 > net->Njuncs) &&
(type == PRV || type == PSV || type == FCV)) return 219;
if (!valvecheck(pr, type, j1, j2)) return 220;
if (type == PRV || type == PSV || type == FCV)
{
if (j1 > net->Njuncs) return setError(parser, 1, 219);
if (j2 > net->Njuncs) return setError(parser, 2, 219);
}
if (!valvecheck(pr, type, j1, j2)) return setError(parser, -1, 220);
// Save valve data
link = &net->Link[net->Nlinks];
@@ -542,12 +568,12 @@ int patterndata(Project *pr)
if (parser->PrevPat != NULL &&
strcmp(parser->Tok[0], parser->PrevPat->ID) == 0) p = parser->PrevPat;
else p = getlistitem(parser->Tok[0], parser->Patlist);
if (p == NULL) return 205;
if (p == NULL) return setError(parser, 0, 205);
// Add parsed multipliers to the pattern
for (i = 1; i <= n; i++)
{
if (!getfloat(parser->Tok[i], &x)) return 202;
if (!getfloat(parser->Tok[i], &x)) return setError(parser, i, 202);
f = (SFloatlist *)malloc(sizeof(SFloatlist));
if (f == NULL) return 101;
f->value = x;
@@ -587,11 +613,11 @@ int curvedata(Project *pr)
if (parser->PrevCurve != NULL &&
strcmp(parser->Tok[0], parser->PrevCurve->ID) == 0) c = parser->PrevCurve;
else c = getlistitem(parser->Tok[0], parser->Curvelist);
if (c == NULL) return 205;
if (c == NULL) return setError(parser, 0, 206);
// Check for valid data
if (!getfloat(parser->Tok[1], &x)) return 202;
if (!getfloat(parser->Tok[2], &y)) return 202;
if (!getfloat(parser->Tok[1], &x)) return setError(parser, 1, 202);
if (!getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
// Add new data point to curve
fx = (SFloatlist *)malloc(sizeof(SFloatlist));
@@ -636,11 +662,11 @@ int coordata(Project *pr)
// Check for valid node ID
if (parser->Ntokens < 3) return 201;
if ((j = findnode(net, parser->Tok[0])) == 0) return 203;
if ((j = findnode(net, parser->Tok[0])) == 0) return setError(parser, 0, 203);
// Check for valid data
if (!getfloat(parser->Tok[1], &x)) return 202;
if (!getfloat(parser->Tok[2], &y)) return 202;
if (!getfloat(parser->Tok[1], &x)) return setError(parser, 1, 202);
if (!getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
// Save coord data
node = &net->Node[j];
@@ -678,23 +704,23 @@ int demanddata(Project *pr)
// Extract data from tokens
n = parser->Ntokens;
if (n < 2) return 201;
if (!getfloat(parser->Tok[1], &y)) return 202;
if (!getfloat(parser->Tok[1], &y)) return setError(parser, 1, 202);
// If MULTIPLY command, save multiplier
if (match(parser->Tok[0], w_MULTIPLY))
{
if (y <= 0.0) return 202;
if (y <= 0.0) return setError(parser, 1, 213);
else hyd->Dmult = y;
return 0;
}
// Otherwise find node (and pattern) being referenced
if ((j = findnode(net, parser->Tok[0])) == 0) return 208;
if (j > net->Njuncs) return 208;
if ((j = findnode(net, parser->Tok[0])) == 0) return setError(parser, 0, 203);
if (j > net->Njuncs) return 0;
if (n >= 3)
{
patlist = getlistitem(parser->Tok[2], parser->Patlist);
if (patlist == NULL) return 205;
if (patlist == NULL) return setError(parser, 2, 205);
p = patlist->i;
}
@@ -761,11 +787,11 @@ int controldata(Project *pr)
// Check that controlled link exists
k = findlink(net, parser->Tok[1]);
if (k == 0) return 204;
if (k == 0) return setError(parser, 1, 204);
// Cannot control a check valve
linktype = net->Link[k].Type;
if (linktype == CVPIPE) return 207;
if (linktype == CVPIPE) return setError(parser, 1, 207);
// Parse control setting into a status level or numerical setting
if (match(parser->Tok[2], w_OPEN))
@@ -780,8 +806,8 @@ int controldata(Project *pr)
if (linktype == PUMP) setting = 0.0;
if (linktype == GPV) setting = net->Link[k].Kc;
}
else if (linktype == GPV) return 206;
else if (!getfloat(parser->Tok[2], &setting)) return 202;
else if (linktype == GPV) return setError(parser, 1, 207);
else if (!getfloat(parser->Tok[2], &setting)) return setError(parser, 2, 202);
// Set status for pump in case speed setting was supplied
// or for pipe if numerical setting was supplied
@@ -789,7 +815,7 @@ int controldata(Project *pr)
{
if (setting != MISSING)
{
if (setting < 0.0) return 202;
if (setting < 0.0) return setError(parser, 2, 211);
else if (setting == 0.0) status = CLOSED;
else status = OPEN;
}
@@ -801,10 +827,10 @@ int controldata(Project *pr)
else
{
if (n < 8) return 201;
if ((i = findnode(net, parser->Tok[5])) == 0) return 203;
if ((i = findnode(net, parser->Tok[5])) == 0) return setError(parser, 5, 203);
if (match(parser->Tok[6], w_BELOW)) ctltype = LOWLEVEL;
else if (match(parser->Tok[6], w_ABOVE)) ctltype = HILEVEL;
else return 201;
else return setError(parser, 6, 213);
}
// Parse control level or time
@@ -814,11 +840,11 @@ int controldata(Project *pr)
case TIMEOFDAY:
if (n == 6) time = hour(parser->Tok[5], "");
if (n == 7) time = hour(parser->Tok[5], parser->Tok[6]);
if (time < 0.0) return 201;
if (time < 0.0) return setError(parser, 5, 213);
break;
case LOWLEVEL:
case HILEVEL:
if (!getfloat(parser->Tok[7], &level)) return 202;
if (!getfloat(parser->Tok[7], &level)) return setError(parser, 7, 202);
break;
}
@@ -866,7 +892,7 @@ int sourcedata(Project *pr)
// Check for enough tokens & that source node exists
n = parser->Ntokens;
if (n < 2) return 201;
if ((j = findnode(net, parser->Tok[0])) == 0) return 203;
if ((j = findnode(net, parser->Tok[0])) == 0) return setError(parser, 0, 203);
// Parse source type
// NOTE: Under old 1.1 format, SourceType not supplied so
@@ -879,14 +905,18 @@ int sourcedata(Project *pr)
else i = 1;
// Parse source quality
if (!getfloat(parser->Tok[i], &c0)) return 202;
if (!getfloat(parser->Tok[i], &c0))
{
if (i == 1) return setError(parser, i, 213);
else return setError(parser, i, 202);
}
// Parse optional source time pattern
if (n > i + 1 && strlen(parser->Tok[i + 1]) > 0 &&
strcmp(parser->Tok[i + 1], "*") != 0)
{
patlist = getlistitem(parser->Tok[i + 1], parser->Patlist);
if (patlist == NULL) return (205);
if (patlist == NULL) return setError(parser, i+1, 205);
p = patlist->i;
}
@@ -925,12 +955,12 @@ int emitterdata(Project *pr)
// Check that node exists & is a junction
n = parser->Ntokens;
if (n < 2) return 201;
if ((j = findnode(net, parser->Tok[0])) == 0) return 203;
if (j > net->Njuncs) return 209;
if ((j = findnode(net, parser->Tok[0])) == 0) return setError(parser, 0, 203);
if (j > net->Njuncs) return 0;
// Parse emitter flow coeff.
if (!getfloat(parser->Tok[1], &k)) return 202;
if (k < 0.0) return 202;
if (!getfloat(parser->Tok[1], &k)) return setError(parser, 1, 202);
if (k < 0.0) return setError(parser, 1, 209);
net->Node[j].Ke = k;
return 0;
}
@@ -956,15 +986,16 @@ int qualdata(Project *pr)
double c0;
Snode *Node = net->Node;
if (net->Nnodes == 0) return 208; // No nodes defined yet
if (net->Nnodes == 0) return setError(parser, 0, 203); // No nodes defined yet
n = parser->Ntokens;
if (n < 2) return 0;
// Single node name supplied
if (n == 2)
{
if ((j = findnode(net,parser->Tok[0])) == 0) return 0;
if (!getfloat(parser->Tok[1], &c0)) return 209;
if ((j = findnode(net,parser->Tok[0])) == 0) return setError(parser, 0, 203);
if (!getfloat(parser->Tok[1], &c0)) return setError(parser, 1, 202);
if (c0 < 0.0) return setError(parser, 1, 209);
Node[j].C0 = c0;
}
@@ -972,7 +1003,8 @@ int qualdata(Project *pr)
else
{
// Parse quality value
if (!getfloat(parser->Tok[2], &c0)) return 209;
if (!getfloat(parser->Tok[2], &c0)) return setError(parser, 2, 202);
if (c0 < 0.0) return setError(parser, 2, 209);
// If numerical node names supplied, then use numerical comparison
// to find which nodes are assigned the quality value
@@ -1034,23 +1066,23 @@ int reactdata(Project *pr)
// Keyword is ORDER
if (match(parser->Tok[0], w_ORDER))
{
if (!getfloat(parser->Tok[n - 1], &y)) return 213;
if (!getfloat(parser->Tok[n - 1], &y)) return setError(parser, n-1, 202);
if (match(parser->Tok[1], w_BULK)) qual->BulkOrder = y;
else if (match(parser->Tok[1], w_TANK)) qual->TankOrder = y;
else if (match(parser->Tok[1], w_WALL))
{
if (y == 0.0) qual->WallOrder = 0.0;
else if (y == 1.0) qual->WallOrder = 1.0;
else return 213;
else return setError(parser, n-1, 213);
}
else return 213;
else return setError(parser, 1, 213);
return 0;
}
// Keyword is ROUGHNESS
if (match(parser->Tok[0], w_ROUGHNESS))
{
if (!getfloat(parser->Tok[n - 1], &y)) return 213;
if (!getfloat(parser->Tok[n - 1], &y)) return setError(parser, n-1, 202);
qual->Rfactor = y;
return 0;
}
@@ -1058,7 +1090,7 @@ int reactdata(Project *pr)
// Keyword is LIMITING
if (match(parser->Tok[0], w_LIMITING))
{
if (!getfloat(parser->Tok[n - 1], &y)) return 213;
if (!getfloat(parser->Tok[n - 1], &y)) return setError(parser, n-1, 202);
qual->Climit = y;
return 0;
}
@@ -1066,10 +1098,10 @@ int reactdata(Project *pr)
// Keyword is GLOBAL
if (match(parser->Tok[0], w_GLOBAL))
{
if (!getfloat(parser->Tok[n - 1], &y)) return 213;
if (!getfloat(parser->Tok[n - 1], &y)) return setError(parser, n-1, 202);
if (match(parser->Tok[1], w_BULK)) qual->Kbulk = y;
else if (match(parser->Tok[1], w_WALL)) qual->Kwall = y;
else return 201;
else return setError(parser, 1, 213);
return 0;
}
@@ -1077,7 +1109,7 @@ int reactdata(Project *pr)
if (match(parser->Tok[0], w_BULK)) item = 1;
else if (match(parser->Tok[0], w_WALL)) item = 2;
else if (match(parser->Tok[0], w_TANK)) item = 3;
else return 201;
else return setError(parser, 0, 213);
// Save the first link/node ID in the first token
strcpy(parser->Tok[0], parser->Tok[1]);
@@ -1086,7 +1118,7 @@ int reactdata(Project *pr)
if (item == 3)
{
// Get the rate coeff. value
if (!getfloat(parser->Tok[n - 1], &y)) return 209;
if (!getfloat(parser->Tok[n - 1], &y)) return setError(parser, n-1, 202);
// Case where just a single tank is specified
if (n == 3)
@@ -1119,7 +1151,7 @@ int reactdata(Project *pr)
else
{
// Get the rate coeff. value
if (!getfloat(parser->Tok[n - 1], &y)) return 211; /* Rate coeff. */
if (!getfloat(parser->Tok[n - 1], &y)) return setError(parser, n-1, 202);
if (net->Nlinks == 0) return 0;
// Case where just a single link is specified
@@ -1181,15 +1213,18 @@ int mixingdata(Project *pr)
double v; // Mixing zone volume fraction
// Check for valid data
if (net->Nnodes == 0) return 208;
if (net->Nnodes == 0) return setError(parser, 0, 203);
n = parser->Ntokens;
if (n < 2) return 0;
if ((j = findnode(net, parser->Tok[0])) <= net->Njuncs) return 0;
if ((m = findmatch(parser->Tok[1], MixTxt)) < 0) return 201;
j = findnode(net, parser->Tok[0]);
if (j == 0) return setError(parser, 0, 203);
if (j <= net->Njuncs) return 0;
if ((m = findmatch(parser->Tok[1], MixTxt)) < 0) return setError(parser, 1, 213);
// Find mixing zone volume fraction (which can't be 0)
v = 1.0;
if ((m == MIX2) && (n == 3) && (!getfloat(parser->Tok[2], &v))) return 209;
if ((m == MIX2) && (n == 3) &&
(!getfloat(parser->Tok[2], &v))) return setError(parser, 2, 202);
if (v == 0.0) v = 1.0;
// Assign mixing data to tank (return if tank is a reservoir)
@@ -1221,26 +1256,29 @@ int statusdata(Project *pr)
double y = 0.0;
char status = ACTIVE;
if (net->Nlinks == 0) return 210;
if (net->Nlinks == 0) return setError(parser, 0, 204);
n = parser->Ntokens - 1;
if (n < 1) return 201;
// Check for legal status setting
if (match(parser->Tok[n], w_OPEN)) status = OPEN;
else if (match(parser->Tok[n], w_CLOSED)) status = CLOSED;
else if (!getfloat(parser->Tok[n], &y)) return 211;
if (y < 0.0) return 211;
else
{
if (!getfloat(parser->Tok[n], &y)) return setError(parser, n, 202);
if (y < 0.0) return setError(parser, n, 211);
}
// A single link ID was supplied
if (n == 1)
{
if ((j = findlink(net, parser->Tok[0])) == 0) return 0;
if ((j = findlink(net, parser->Tok[0])) == 0) return setError(parser, 0, 204);
// Cannot change status of a Check Valve
if (net->Link[j].Type == CVPIPE) return 211;
if (net->Link[j].Type == CVPIPE) return setError(parser, 0, 207);
// Cannot change setting for a GPV
if (net->Link[j].Type == GPV && status == ACTIVE) return 211;
if (net->Link[j].Type == GPV && status == ACTIVE) return setError(parser, 0, 207);
changestatus(net, j, status, y);
}
@@ -1297,7 +1335,8 @@ int energydata(Project *pr)
// First keyword is DEMAND
if (match(parser->Tok[0], w_DMNDCHARGE))
{
if (!getfloat(parser->Tok[2], &y)) return 213;
if (!getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
if (y < 0.0) return setError(parser, 2, 213);
hyd->Dcost = y;
return 0;
}
@@ -1313,20 +1352,17 @@ int energydata(Project *pr)
{
if (n < 4) return 201;
k = findlink(net,parser->Tok[1]);
if (k == 0) return 216;
if (Link[k].Type != PUMP) return 216;
if (k == 0) return setError(parser, 1, 216);
if (Link[k].Type != PUMP) return setError(parser, 1, 216);
j = findpump(net, k);
}
else return 201;
else return setError(parser, 0, 213);
// PRICE parameter being set
if (match(parser->Tok[n - 2], w_PRICE))
{
if (!getfloat(parser->Tok[n - 1], &y))
{
if (j == 0) return 213;
else return 217;
}
if (!getfloat(parser->Tok[n - 1], &y)) return setError(parser, n-1, 202);
if (y < 0.0) return setError(parser, n-1, 217);
if (j == 0) hyd->Ecost = y;
else Pump[j].Ecost = y;
return 0;
@@ -1336,11 +1372,7 @@ int energydata(Project *pr)
else if (match(parser->Tok[n - 2], w_PATTERN))
{
listitem = getlistitem(parser->Tok[n - 1], parser->Patlist);
if (listitem == NULL)
{
if (j == 0) return 213;
else return 217;
}
if (listitem == NULL) return setError(parser, n - 1, 205);
if (j == 0) hyd->Epat = listitem->i;
else Pump[j].Epat = listitem->i;
return 0;
@@ -1351,14 +1383,14 @@ int energydata(Project *pr)
{
if (j == 0)
{
if (!getfloat(parser->Tok[n - 1], &y)) return 213;
if (y <= 0.0) return 213;
if (!getfloat(parser->Tok[n - 1], &y)) return setError(parser, n - 1, 202);
if (y <= 0.0) return setError(parser, n - 1, 217);
hyd->Epump = y;
}
else
{
listitem = getlistitem(parser->Tok[n - 1], parser->Curvelist);
if (listitem == NULL) return 217;
if (listitem == NULL) return setError(parser, n - 1, 206);
Pump[j].Ecurve = listitem->i;
net->Curve[listitem->i].Type = E_CURVE;
}
@@ -1402,8 +1434,8 @@ int reportdata(Project *pr)
// Value for page size
if (match(parser->Tok[0], w_PAGE))
{
if (!getfloat(parser->Tok[n], &y)) return 213;
if (y < 0.0 || y > 255.0) return 213;
if (!getfloat(parser->Tok[n], &y)) return setError(parser, n, 202);
if (y < 0.0 || y > 255.0) return setError(parser, n, 213);
rpt->PageSize = (int)y;
return 0;
}
@@ -1448,10 +1480,10 @@ int reportdata(Project *pr)
else if (match(parser->Tok[n], w_ALL)) rpt->Nodeflag = 1; // All nodes
else
{
if (net->Nnodes == 0) return 208;
if (net->Nnodes == 0) return setError(parser, 1, 208);
for (i = 1; i <= n; i++)
{
if ((j = findnode(net, parser->Tok[i])) == 0) return 208;
if ((j = findnode(net, parser->Tok[i])) == 0) return setError(parser, i, 208);
net->Node[j].Rpt = 1;
}
rpt->Nodeflag = 2;
@@ -1466,10 +1498,10 @@ int reportdata(Project *pr)
else if (match(parser->Tok[n], w_ALL)) rpt->Linkflag = 1;
else
{
if (net->Nlinks == 0) return 210;
if (net->Nlinks == 0) return setError(parser, 1, 210);
for (i = 1; i <= n; i++)
{
if ((j = findlink(net, parser->Tok[i])) == 0) return 210;
if ((j = findlink(net, parser->Tok[i])) == 0) return setError(parser, i, 210);
net->Link[j].Rpt = 1;
}
rpt->Linkflag = 2;
@@ -1483,7 +1515,7 @@ int reportdata(Project *pr)
else i = findmatch(parser->Tok[0], Fldname);
if (i >= 0)
{
if (i > FRICTION) return 201;
if (i > FRICTION) return setError(parser, 0, 213);
if (parser->Ntokens == 1 || match(parser->Tok[1], w_YES))
{
rpt->Field[i].Enabled = TRUE;
@@ -1497,14 +1529,14 @@ int reportdata(Project *pr)
}
// Get field qualifier type
if (parser->Ntokens < 3) return (201);
if (parser->Ntokens < 3) return 201;
if (match(parser->Tok[1], w_BELOW)) j = LOW;
else if (match(parser->Tok[1], w_ABOVE)) j = HI;
else if (match(parser->Tok[1], w_PRECISION)) j = PREC;
else return 201;
else return setError(parser, 1, 213);
// Get field qualifier value
if (!getfloat(parser->Tok[2], &y)) return 201;
if (!getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
if (j == PREC)
{
rpt->Field[i].Enabled = TRUE;
@@ -1566,7 +1598,7 @@ int timedata(Project *pr)
else if (match(parser->Tok[n], w_MIN)) rpt->Tstatflag = MIN;
else if (match(parser->Tok[n], w_MAX)) rpt->Tstatflag = MAX;
else if (match(parser->Tok[n], w_RANGE)) rpt->Tstatflag = RANGE;
else return 201;
else return setError(parser, n, 213);
return 0;
}
@@ -1581,7 +1613,10 @@ int timedata(Project *pr)
{
if ((y = hour(parser->Tok[n], "")) < 0.0)
{
if ((y = hour(parser->Tok[n - 1], parser->Tok[n])) < 0.0) return 213;
if ((y = hour(parser->Tok[n - 1], parser->Tok[n])) < 0.0)
{
return setError(parser, n-1, 213);
}
}
}
t = (long)(3600.0 * y + 0.5);
@@ -1596,16 +1631,16 @@ int timedata(Project *pr)
{
if (match(parser->Tok[1], w_TIME)) time->Pstep = t;
else if (match(parser->Tok[1], w_START)) time->Pstart = t;
else return 201;
else return setError(parser, 1, 213);
}
else if (match(parser->Tok[0], w_REPORT))
{
if (match(parser->Tok[1], w_TIME)) time->Rstep = t;
else if (match(parser->Tok[1], w_START)) time->Rstart = t;
else return 201;
else return setError(parser, 1, 213);
}
else if (match(parser->Tok[0], w_START)) time->Tstart = t % SECperDAY;
else return 201;
else return setError(parser, 0, 213);
return 0;
}
@@ -1633,7 +1668,7 @@ int optiondata(Project *pr)
int optionchoice(Project *pr, int n)
/*
**--------------------------------------------------------------
** Input: n = index of last input token saved in par->Tok[]
** Input: n = index of last input token
** Output: returns error code or 0 if option belongs to
** those listed below, or -1 otherwise
** Purpose: processes fixed choice [OPTIONS] data
@@ -1678,7 +1713,7 @@ int optionchoice(Project *pr, int n)
else if (match(parser->Tok[1], w_CMD)) parser->Flowflag = CMD;
else if (match(parser->Tok[1], w_MLD)) parser->Flowflag = MLD;
else if (match(parser->Tok[1], w_SI)) parser->Flowflag = LPS;
else return 201;
else return setError(parser, 1, 213);
}
// PRESSURE units
@@ -1689,7 +1724,7 @@ int optionchoice(Project *pr, int n)
else if (match(parser->Tok[1], w_PSI)) parser->Pressflag = PSI;
else if (match(parser->Tok[1], w_KPA)) parser->Pressflag = KPA;
else if (match(parser->Tok[1], w_METERS)) parser->Pressflag = METERS;
else return 201;
else return setError(parser, 1, 213);
}
// HEADLOSS formula
@@ -1699,7 +1734,7 @@ int optionchoice(Project *pr, int n)
else if (match(parser->Tok[1], w_HW)) hyd->Formflag = HW;
else if (match(parser->Tok[1], w_DW)) hyd->Formflag = DW;
else if (match(parser->Tok[1], w_CM)) hyd->Formflag = CM;
else return 201;
else return setError(parser, 1, 213);
}
// HYDRUALICS USE/SAVE file option
@@ -1708,14 +1743,14 @@ int optionchoice(Project *pr, int n)
if (n < 2) return 0;
else if (match(parser->Tok[1], w_USE)) out->Hydflag = USE;
else if (match(parser->Tok[1], w_SAVE)) out->Hydflag = SAVE;
else return 201;
else return setError(parser, 1, 213);
strncpy(out->HydFname, parser->Tok[2], MAXFNAME);
}
// Water QUALITY option
else if (match(parser->Tok[0], w_QUALITY))
{
if (n < 1) return (0);
if (n < 1) return 0;
else if (match(parser->Tok[1], w_NONE)) qual->Qualflag = NONE;
else if (match(parser->Tok[1], w_CHEM)) qual->Qualflag = CHEM;
else if (match(parser->Tok[1], w_AGE)) qual->Qualflag = AGE;
@@ -1730,10 +1765,10 @@ int optionchoice(Project *pr, int n)
{
// Copy Trace Node ID to parser->Tok[0] for error reporting
strcpy(parser->Tok[0], "");
if (n < 2) return 212;
if (n < 2) return 201;
strcpy(parser->Tok[0], parser->Tok[2]);
qual->TraceNode = findnode(net, parser->Tok[2]);
if (qual->TraceNode == 0) return 212;
if (qual->TraceNode == 0) return setError(parser, 2, 212);
strncpy(qual->ChemName, u_PERCENT, MAXID);
strncpy(qual->ChemUnits, parser->Tok[2], MAXID);
}
@@ -1766,7 +1801,7 @@ int optionchoice(Project *pr, int n)
if (n >= 2) hyd->ExtraIter = atoi(parser->Tok[2]);
else hyd->ExtraIter = 0;
}
else return 201;
else return setError(parser, 1, 213);
}
// Default demand PATTERN
@@ -1782,7 +1817,7 @@ int optionchoice(Project *pr, int n)
if (n < 2) return 0;
if (!match(parser->Tok[1], w_MODEL)) return -1;
choice = findmatch(parser->Tok[2], DemandModelTxt);
if (choice < 0) return 201;
if (choice < 0) return setError(parser, 2, 213);
hyd->DemandModel = choice;
}
@@ -1844,12 +1879,12 @@ int optionvalue(Project *pr, int n)
if (n < nvalue) return 0;
// Check for valid numerical input
if (!getfloat(parser->Tok[nvalue], &y)) return 213;
if (!getfloat(parser->Tok[nvalue], &y)) return setError(parser, nvalue, 202);
// Quality tolerance option (which can be 0)
if (match(tok0, w_TOLERANCE))
{
if (y < 0.0) return 213;
if (y < 0.0) return setError(parser, nvalue, 213);
qual->Ctol = y;
return 0;
}
@@ -1857,7 +1892,7 @@ int optionvalue(Project *pr, int n)
// Diffusivity
if (match(tok0, w_DIFFUSIVITY))
{
if (y < 0.0) return 213;
if (y < 0.0) return setError(parser, nvalue, 213);
qual->Diffus = y;
return 0;
}
@@ -1872,7 +1907,7 @@ int optionvalue(Project *pr, int n)
// Flow change limit
else if (match(tok0, w_FLOWCHANGE))
{
if (y < 0.0) return 213;
if (y < 0.0) return setError(parser, nvalue, 213);
hyd->FlowChangeLimit = y;
return 0;
}
@@ -1880,7 +1915,7 @@ int optionvalue(Project *pr, int n)
// Head loss error limit
else if (match(tok0, w_HEADERROR))
{
if (y < 0.0) return 213;
if (y < 0.0) return setError(parser, nvalue, 213);
hyd->HeadErrorLimit = y;
return 0;
}
@@ -1888,25 +1923,25 @@ int optionvalue(Project *pr, int n)
// Pressure dependent demand parameters
else if (match(tok0, w_MINIMUM))
{
if (y < 0.0) return 213;
if (y < 0.0) return setError(parser, nvalue, 213);
hyd->Pmin = y;
return 0;
}
else if (match(tok0, w_REQUIRED))
{
if (y < 0.0) return 213;
if (y < 0.0) return setError(parser, nvalue, 213);
hyd->Preq = y;
return 0;
}
else if (match(tok0, w_PRESSURE))
{
if (y < 0.0) return 213;
if (y < 0.0) return setError(parser, nvalue, 213);
hyd->Pexp = y;
return 0;
}
// All other options must be > 0
if (y <= 0.0) return 213;
if (y <= 0.0) return setError(parser, nvalue, 213);
// Assign value to all other options
if (match(tok0, w_VISCOSITY)) hyd->Viscos = y;

View File

@@ -7,7 +7,7 @@
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 11/27/2018
Last Updated: 12/15/2018
******************************************************************************
*/
@@ -791,11 +791,14 @@ char *geterrmsg(int errcode, char *msg)
**----------------------------------------------------------------
*/
{
switch (errcode) { /* Warnings */
//#define DAT(code,enumer,string) case code: strcpy(msg, string); break;
#define DAT(code,enumer,string) case code: sprintf(msg, "Error %d: %s", code, string); break;
switch (errcode)
{
//#define DAT(code,string) case code: sprintf(msg, "%s", string); break;
#define DAT(code,string) case code: strcpy(msg, string); break;
#include "errors.dat"
#undef DAT
default:
strcpy(msg, "");
}
@@ -810,13 +813,15 @@ void errmsg(Project *pr, int errcode)
**----------------------------------------------------------------
*/
{
char errmsg[MAXMSG + 1] = "";
if (errcode == 309) /* Report file write error - */
{ /* Do not write msg to file. */
}
else if (pr->report.RptFile != NULL && pr->report.Messageflag)
else if (pr->report.RptFile != NULL && pr->report.Messageflag && errcode > 100)
{
writeline(pr, geterrmsg(errcode, pr->Msg));
sprintf(pr->Msg, "Error %d: %s", errcode, geterrmsg(errcode, errmsg));
writeline(pr, pr->Msg);
}
}

View File

@@ -7,7 +7,7 @@
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 11/27/2018
Last Updated: 12/15/2018
******************************************************************************
*/
@@ -565,7 +565,8 @@ typedef struct {
MaxPats, // Pattern count " " "
MaxCurves, // Curve count " " "
Ntokens, // Number of tokens in line of input
Ntitle; // Number of title lines
Ntitle, // Number of title lines
ErrTok; // Index of error-producing token
STmplist
*Patlist, // Temporary time pattern list

View File

@@ -25,8 +25,8 @@ set SCRIPT_HOME=%~dp0
set TEST_HOME=%~1
set EXAMPLES_VER=1.0.2-dev.4
set BENCHMARK_VER=220dev4
set EXAMPLES_VER=1.0.2-dev.5
set BENCHMARK_VER=220dev5
set TESTFILES_URL=https://github.com/OpenWaterAnalytics/epanet-example-networks/archive/v%EXAMPLES_VER%.zip

View File

@@ -18,7 +18,7 @@ setlocal
set NRTEST_SCRIPT_PATH=%~1
set TEST_SUITE_PATH=%~2
set BENCHMARK_VER=220dev4
set BENCHMARK_VER=220dev5
set NRTEST_EXECUTE_CMD=python %NRTEST_SCRIPT_PATH%\nrtest execute