Error reporting fixes and re-formatting (issue #358)

This commit is contained in:
Lew Rossman
2018-12-15 15:13:19 -05:00
parent 4e3b96e61c
commit f1175b1f92
7 changed files with 415 additions and 383 deletions

View File

@@ -7,7 +7,7 @@
Authors: see AUTHORS Authors: see AUTHORS
Copyright: see AUTHORS Copyright: see AUTHORS
License: see LICENSE License: see LICENSE
Last Updated: 11/27/2018 Last Updated: 12/15/2018
****************************************************************************** ******************************************************************************
*/ */
@@ -26,7 +26,9 @@
#include "text.h" #include "text.h"
#include "enumstxt.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; p->report.Statflag = (char)code;
} }
else errcode = 202; else errcode = 251;
return errcode; 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) switch (errcode)
{ {
@@ -938,8 +941,10 @@ int DLLEXPORT EN_geterror(int errcode, char *errmsg, int n)
strncpy(errmsg, WARN6, n); strncpy(errmsg, WARN6, n);
break; break;
default: default:
geterrmsg(errcode, newMsg); sprintf(msg1, "Error %d: ", errcode);
strncpy(errmsg, newMsg, n); 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) if (strlen(errmsg) == 0)
return 251; 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); *value = (EN_API_FLOAT_TYPE)(p->quality.MassBalance.ratio);
break; break;
default: default:
*value = 0.0;
break; break;
} }
return 0; return 0;
@@ -1067,22 +1073,22 @@ int DLLEXPORT EN_setoption(EN_Project p, int code, EN_API_FLOAT_TYPE v)
switch (code) switch (code)
{ {
case EN_TRIALS: case EN_TRIALS:
if (value < 1.0) return 202; if (value < 1.0) return 213;
hyd->MaxIter = (int)value; hyd->MaxIter = (int)value;
break; break;
case EN_ACCURACY: 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; hyd->Hacc = value;
break; break;
case EN_TOLERANCE: case EN_TOLERANCE:
if (value < 0.0) return 202; if (value < 0.0) return 213;
qual->Ctol = value / Ucf[QUALITY]; qual->Ctol = value / Ucf[QUALITY];
break; break;
case EN_EMITEXPON: case EN_EMITEXPON:
if (value <= 0.0) return 202; if (value <= 0.0) return 213;
n = 1.0 / value; n = 1.0 / value;
ucf = pow(Ucf[FLOW], n) / Ucf[PRESSURE]; ucf = pow(Ucf[FLOW], n) / Ucf[PRESSURE];
for (i = 1; i <= Njuncs; i++) 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; break;
case EN_DEMANDMULT: case EN_DEMANDMULT:
if (value <= 0.0) return 202; if (value <= 0.0) return 213;
hyd->Dmult = value; hyd->Dmult = value;
break; break;
case EN_HEADERROR: case EN_HEADERROR:
if (value < 0.0) return 202; if (value < 0.0) return 213;
hyd->HeadErrorLimit = value / Ucf[HEAD]; hyd->HeadErrorLimit = value / Ucf[HEAD];
break; break;
case EN_FLOWCHANGE: case EN_FLOWCHANGE:
if (value < 0.0) return 202; if (value < 0.0) return 213;
hyd->FlowChangeLimit = value / Ucf[FLOW]; hyd->FlowChangeLimit = value / Ucf[FLOW];
break; break;
@@ -1319,7 +1325,7 @@ int DLLEXPORT EN_settimeparam(EN_Project p, int code, long value)
Times *time = &p->times; Times *time = &p->times;
if (!p->Openflag) return 102; if (!p->Openflag) return 102;
if (value < 0) return 202; if (value < 0) return 213;
switch (code) switch (code)
{ {
case EN_DURATION: case EN_DURATION:
@@ -1328,7 +1334,7 @@ int DLLEXPORT EN_settimeparam(EN_Project p, int code, long value)
break; break;
case EN_HYDSTEP: case EN_HYDSTEP:
if (value == 0) return 202; if (value == 0) return 213;
time->Hstep = value; time->Hstep = value;
time->Hstep = MIN(time->Pstep, time->Hstep); time->Hstep = MIN(time->Pstep, time->Hstep);
time->Hstep = MIN(time->Rstep, 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; break;
case EN_QUALSTEP: case EN_QUALSTEP:
if (value == 0) return 202; if (value == 0) return 213;
time->Qstep = value; time->Qstep = value;
time->Qstep = MIN(time->Qstep, time->Hstep); time->Qstep = MIN(time->Qstep, time->Hstep);
break; break;
case EN_PATTERNSTEP: case EN_PATTERNSTEP:
if (value == 0) return 202; if (value == 0) return 213;
time->Pstep = value; time->Pstep = value;
if (time->Hstep > time->Pstep) time->Hstep = time->Pstep; if (time->Hstep > time->Pstep) time->Hstep = time->Pstep;
break; break;
@@ -1352,24 +1358,24 @@ int DLLEXPORT EN_settimeparam(EN_Project p, int code, long value)
break; break;
case EN_REPORTSTEP: case EN_REPORTSTEP:
if (value == 0) return 202; if (value == 0) return 213;
time->Rstep = value; time->Rstep = value;
if (time->Hstep > time->Rstep) time->Hstep = time->Rstep; if (time->Hstep > time->Rstep) time->Hstep = time->Rstep;
break; break;
case EN_REPORTSTART: case EN_REPORTSTART:
if (time->Rstart > time->Dur) return 202; if (time->Rstart > time->Dur) return 213;
time->Rstart = value; time->Rstart = value;
break; break;
case EN_RULESTEP: case EN_RULESTEP:
if (value == 0) return 202; if (value == 0) return 213;
time->Rulestep = value; time->Rulestep = value;
time->Rulestep = MIN(time->Rulestep, time->Hstep); time->Rulestep = MIN(time->Rulestep, time->Hstep);
break; break;
case EN_STATISTIC: case EN_STATISTIC:
if (value > RANGE) return 202; if (value > RANGE) return 213;
rpt->Tstatflag = (char)value; rpt->Tstatflag = (char)value;
break; break;
@@ -1401,16 +1407,26 @@ int DLLEXPORT EN_getqualinfo(EN_Project p, int *qualcode, char *chemname,
*/ */
{ {
EN_getqualtype(p, qualcode, tracenode); EN_getqualtype(p, qualcode, tracenode);
if (p->quality.Qualflag == TRACE) if (p->quality.Qualflag == CHEM)
{
strncpy(chemname, "", MAXID);
strncpy(chemunits, "dimensionless", MAXID);
}
else
{ {
strncpy(chemname, p->quality.ChemName, MAXID); strncpy(chemname, p->quality.ChemName, MAXID);
strncpy(chemunits, p->quality.ChemUnits, 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; return 0;
} }
@@ -1469,9 +1485,9 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualcode, char *chemname,
if (qual->Qualflag == TRACE) // Source trace analysis if (qual->Qualflag == TRACE) // Source trace analysis
{ {
qual->TraceNode = findnode(net, tracenode); qual->TraceNode = findnode(net, tracenode);
if (qual->TraceNode == 0) return 203; if (qual->TraceNode == 0) return 212;
strncpy(qual->ChemName, u_PERCENT, MAXID); strncpy(qual->ChemName, w_TRACE, MAXID);
strncpy(qual->ChemUnits, tracenode, MAXID); strncpy(qual->ChemUnits, u_PERCENT, MAXID);
strcpy(rpt->Field[QUALITY].Units, u_PERCENT); strcpy(rpt->Field[QUALITY].Units, u_PERCENT);
} }
if (qual->Qualflag == AGE) // Water age analysis 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 // Check that node exists
if (!p->Openflag) return 102; 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; if (actionCode < EN_UNCONDITIONAL || actionCode > EN_CONDITIONAL) return 251;
// Can't delete a water quality trace node // 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; break;
case EN_TANKLEVEL: case EN_TANKLEVEL:
if (index <= nJuncs) return 251; if (index <= nJuncs) return 0;
v = (Tank[index - nJuncs].H0 - Node[index].El) * Ucf[ELEV]; v = (Tank[index - nJuncs].H0 - Node[index].El) * Ucf[ELEV];
break; break;
@@ -2018,7 +2034,7 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
break; break;
case EN_TANKVOLUME: case EN_TANKVOLUME:
if (index <= nJuncs) return 251; if (index <= nJuncs) return 0;
v = tankvolume(p, index - nJuncs, NodeHead[index]) * Ucf[VOLUME]; v = tankvolume(p, index - nJuncs, NodeHead[index]) * Ucf[VOLUME];
break; break;
@@ -2103,14 +2119,14 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int code, EN_API_FLOAT_TY
break; break;
case EN_EMITTER: case EN_EMITTER:
if (index > nJuncs) return 203; if (index > nJuncs) return 0;
if (value < 0.0) return 202; if (value < 0.0) return 209;
if (value > 0.0) value = pow((Ucf[FLOW] / value), hyd->Qexp) / Ucf[PRESSURE]; if (value > 0.0) value = pow((Ucf[FLOW] / value), hyd->Qexp) / Ucf[PRESSURE];
Node[index].Ke = value; Node[index].Ke = value;
break; break;
case EN_INITQUAL: case EN_INITQUAL:
if (value < 0.0) return 202; if (value < 0.0) return 209;
Node[index].C0 = value / Ucf[QUALITY]; Node[index].C0 = value / Ucf[QUALITY];
if (index > nJuncs) Tank[index - nJuncs].C = Node[index].C0; if (index > nJuncs) Tank[index - nJuncs].C = Node[index].C0;
break; 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_SOURCEQUAL:
case EN_SOURCETYPE: case EN_SOURCETYPE:
case EN_SOURCEPAT: case EN_SOURCEPAT:
if (value < 0.0) return 202; if (value < 0.0) return 209;
source = Node[index].S; source = Node[index].S;
if (source == NULL) 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; if (j < CONCEN || j > FLOWPACED) return 251;
else source->Type = (char)j; else source->Type = (char)j;
} }
return 0; break;
case EN_TANKLEVEL: case EN_TANKLEVEL:
if (index <= nJuncs) return 251; if (index <= nJuncs) return 0;
j = index - nJuncs; j = index - nJuncs;
if (Tank[j].A == 0.0) /* Tank is a reservoir */ 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 else
{ {
value = Node[index].El + value / Ucf[ELEV]; 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].H0 = value;
Tank[j].V0 = tankvolume(p, j, Tank[j].H0); Tank[j].V0 = tankvolume(p, j, Tank[j].H0);
// Resetting Volume in addition to initial volume // 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; break;
case EN_TANKDIAM: case EN_TANKDIAM:
if (value <= 0.0) return 202; if (value <= 0.0) return 209;
if (index <= nJuncs) return 251; if (index <= nJuncs) return 0;
j = index - nJuncs; j = index - nJuncs;
if (j > 0 && Tank[j].A > 0.0) if (Tank[j].A > 0.0)
{ {
value /= Ucf[ELEV]; value /= Ucf[ELEV];
Tank[j].A = PI * SQR(value) / 4.0; 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].V0 = tankvolume(p, j, Tank[j].H0);
Tank[j].Vmax = tankvolume(p, j, Tank[j].Hmax); Tank[j].Vmax = tankvolume(p, j, Tank[j].Hmax);
} }
else return 251;
break; break;
case EN_MINVOLUME: case EN_MINVOLUME:
if (value < 0.0) return 202; if (value < 0.0) return 209;
if (index <= nJuncs) return 251; if (index <= nJuncs) return 0;
j = index - nJuncs; 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].Vmin = value / Ucf[VOLUME];
Tank[j].V0 = tankvolume(p, j, Tank[j].H0); Tank[j].V0 = tankvolume(p, j, Tank[j].H0);
Tank[j].Vmax = tankvolume(p, j, Tank[j].Hmax); Tank[j].Vmax = tankvolume(p, j, Tank[j].Hmax);
} }
else return 251;
break; break;
case EN_MINLEVEL: case EN_MINLEVEL:
if (value < 0.0) return 202; if (value < 0.0) return 209;
if (index <= nJuncs) return 251; // not a tank or reservoir if (index <= nJuncs) return 0; // not a tank or reservoir
j = index - nJuncs; 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; hTmp = value / Ucf[ELEV] + Node[index].El;
if (hTmp < Tank[j].Hmax && hTmp <= Tank[j].H0) 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].Hmin = hTmp;
Tank[j].Vmin = (Tank[j].Hmin - Node[index].El) * Tank[j].A; Tank[j].Vmin = (Tank[j].Hmin - Node[index].El) * Tank[j].A;
} }
else return 251; else return 209;
break; break;
case EN_MAXLEVEL: case EN_MAXLEVEL:
if (value < 0.0) return 202; if (value < 0.0) return 209;
if (index <= nJuncs) return 251; // not a tank or reservoir if (index <= nJuncs) return 0; // not a tank or reservoir
j = index - nJuncs; 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; hTmp = value / Ucf[ELEV] + Node[index].El;
if (hTmp > Tank[j].Hmin && hTmp >= Tank[j].H0) 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].Hmax = hTmp;
Tank[j].Vmax = tankvolume(p, j, Tank[j].Hmax); Tank[j].Vmax = tankvolume(p, j, Tank[j].Hmax);
} }
else return 251; else return 209;
break; break;
case EN_MIXMODEL: case EN_MIXMODEL:
j = ROUND(value); j = ROUND(value);
if (index <= nJuncs) return 251; if (index <= nJuncs) return 0;
if (j < MIX1 || j > LIFO) return 202; if (j < MIX1 || j > LIFO) return 251;
if (index > nJuncs && Tank[index - nJuncs].A > 0.0) if (Tank[index - nJuncs].A > 0.0)
{ {
Tank[index - nJuncs].MixModel = (char)j; Tank[index - nJuncs].MixModel = (char)j;
} }
else return 251;
break; break;
case EN_MIXFRACTION: case EN_MIXFRACTION:
if (value < 0.0 || value > 1.0) return 202; if (index <= nJuncs) return 0;
if (index <= nJuncs) return 251; if (value < 0.0 || value > 1.0) return 209;
j = index - nJuncs; j = index - nJuncs;
if (j > 0 && Tank[j].A > 0.0) if (Tank[j].A > 0.0)
{ {
Tank[j].V1max = value * Tank[j].Vmax; Tank[j].V1max = value * Tank[j].Vmax;
} }
break; break;
case EN_TANK_KBULK: case EN_TANK_KBULK:
if (index <= nJuncs) return 251; if (index <= nJuncs) return 0;
j = index - nJuncs; j = index - nJuncs;
if (j > 0 && Tank[j].A > 0.0) if (Tank[j].A > 0.0)
{ {
Tank[j].Kb = value / SECperDAY; Tank[j].Kb = value / SECperDAY;
qual->Reactflag = 1; qual->Reactflag = 1;
} }
else return 251;
break; break;
default: 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 (!p->Openflag) return 102;
if (index < 1 || index > p->network.Nnodes) return 203; if (index < 1 || index > p->network.Nnodes) return 203;
// check if node have coords // check if node has coords
node = &net->Node[index]; node = &net->Node[index];
if (node->X == MISSING || if (node->X == MISSING ||
node->Y == MISSING) return 254; 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 (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.DemandModel = type;
p->hydraul.Pmin = pmin / p->Ucf[PRESSURE]; p->hydraul.Pmin = pmin / p->Ucf[PRESSURE];
p->hydraul.Preq = preq / 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 (node1 < 0 || node1 > net->Nnodes) return 203;
if (node2 < 0 || node2 > 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 // Check for illegal valve connection
type = net->Link[index].Type; type = net->Link[index].Type;
if (type == EN_PRV || type == EN_PSV || type == EN_FCV) 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; Hydraul *hyd = &p->hydraul;
double a, h, q, v = 0.0; double a, h, q, v = 0.0;
int returnValue = 0;
int pmp; int pmp;
Slink *Link = net->Link; Slink *Link = net->Link;
Spump *Pump = net->Pump; 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) if (Link[index].Type == EN_PUMP)
{ {
v = (double)Pump[findpump(&p->network, index)].Hcurve; v = (double)Pump[findpump(&p->network, index)].Hcurve;
if (v == 0) returnValue = 226;
}
else
{
v = 0;
returnValue = 211;
} }
break; break;
@@ -3197,20 +3205,14 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, EN_LinkProperty code,
if (Link[index].Type == EN_PUMP) if (Link[index].Type == EN_PUMP)
{ {
v = (double)Pump[findpump(&p->network, index)].Ecurve; v = (double)Pump[findpump(&p->network, index)].Ecurve;
if (v == 0) returnValue = 268;
}
else
{
v = 0;
returnValue = 211;
} }
break;
default: default:
v = 0; return 251;
returnValue = 251;
} }
*value = (EN_API_FLOAT_TYPE)v; *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) 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: case EN_DIAMETER:
if (Link[index].Type != EN_PUMP) if (Link[index].Type != EN_PUMP)
{ {
if (value <= 0.0) return 202; if (value <= 0.0) return 211;
value /= Ucf[DIAM]; // Convert to feet value /= Ucf[DIAM]; // Convert to feet
r = Link[index].Diam / value; // Ratio of old to new diam r = Link[index].Diam / value; // Ratio of old to new diam
Link[index].Km *= SQR(r) * SQR(r); // Adjust minor loss factor 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: case EN_LENGTH:
if (Link[index].Type <= EN_PIPE) if (Link[index].Type <= EN_PIPE)
{ {
if (value <= 0.0) return 202; if (value <= 0.0) return 211;
Link[index].Len = value / Ucf[ELEV]; Link[index].Len = value / Ucf[ELEV];
resistcoeff(p, index); 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: case EN_ROUGHNESS:
if (Link[index].Type <= EN_PIPE) if (Link[index].Type <= EN_PIPE)
{ {
if (value <= 0.0) return 202; if (value <= 0.0) return 211;
Link[index].Kc = value; Link[index].Kc = value;
if (hyd->Formflag == DW) Link[index].Kc /= (1000.0 * Ucf[ELEV]); if (hyd->Formflag == DW) Link[index].Kc /= (1000.0 * Ucf[ELEV]);
resistcoeff(p, index); 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: case EN_MINORLOSS:
if (Link[index].Type != EN_PUMP) 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) / Link[index].Km = 0.02517 * value / SQR(Link[index].Diam) /
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 // Cannot set status for a check valve
if (Link[index].Type == EN_CVPIPE) return 207; if (Link[index].Type == EN_CVPIPE) return 207;
s = (char)ROUND(value); s = (char)ROUND(value);
if (s < 0 || s > 1) return 251; if (s < 0 || s > 1) return 211;
if (code == EN_INITSTATUS) if (code == EN_INITSTATUS)
{ {
setlinkstatus(p, index, s, &Link[index].Status, &Link[index].Kc); 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_INITSETTING:
case EN_SETTING: 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) if (Link[index].Type == EN_PIPE || Link[index].Type == EN_CVPIPE)
{ {
return EN_setlinkvalue(p, index, EN_ROUGHNESS, v); 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: case EN_TCV:
break; break;
case EN_GPV: case EN_GPV:
return 202; // Cannot modify setting for GPV return 207; // Cannot modify setting for GPV
default: default:
return 251; return 0;
} }
if (code == EN_INITSETTING) if (code == EN_INITSETTING)
{ {
@@ -3379,7 +3381,8 @@ int DLLEXPORT EN_getpumptype(EN_Project p, int index, int *type)
*type = -1; *type = -1;
if (!p->Openflag) return 102; 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; *type = Pump[findpump(&p->network, index)].Ptype;
return 0; return 0;
} }
@@ -3399,8 +3402,10 @@ int DLLEXPORT EN_getheadcurveindex(EN_Project p, int index, int *curveindex)
Spump *Pump = net->Pump; Spump *Pump = net->Pump;
const int Nlinks = net->Nlinks; const int Nlinks = net->Nlinks;
*curveindex = 0;
if (!p->Openflag) return 102; 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; *curveindex = Pump[findpump(net, index)].Hcurve;
return 0; return 0;
} }
@@ -3426,7 +3431,8 @@ int DLLEXPORT EN_setheadcurveindex(EN_Project p, int index, int curveindex)
// Check for valid parameters // Check for valid parameters
if (!p->Openflag) return 102; 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; if (curveindex <= 0 || curveindex > net->Ncurves) return 206;
// Assign the new curve to the pump // 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 // Check for valid arguments
if (!p->Openflag) return 102; if (!p->Openflag) return 102;
if (index <= 0 || index > net->Npats) return 205; 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 // Re-set number of time periods & reallocate memory for multipliers
Pattern[index].Length = n; 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 (index <= 0 || index > net->Ncurves) return 206;
if (n <= 0) return 202; 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 // Re-set number of points & reallocate memory for values
curve = &net->Curve[index]; curve = &net->Curve[index];
curve->Npts = n; 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") // These errors apply only to an input file
DAT(101,ENERR_INSUF_MEM,"insufficient memory available") DAT(200,"one or more errors in input file")
DAT(102,ENERR_NO_NET_DATA,"no network data available") DAT(201,"syntax error")
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")
DAT(200,ENERR_INP_ERR,"one or more errors in input file") // These errors apply to both an input file and to API functions
DAT(201,ENERR_SYNTAX_LINE,"syntax error in following line of section") DAT(202,"illegal numeric value")
DAT(202,ENERR_ILLEGAL_NUM,"function call contains illegal numeric value") DAT(203,"undefined node")
DAT(203,ENERR_UNDEF_NODE,"function call refers to undefined node") DAT(204,"undefined link")
DAT(204,ENERR_UNDEF_LINK,"function call refers to undefined link") DAT(205,"undefined time pattern")
DAT(205,ENERR_UNDEF_PAT,"function call refers to undefined time pattern") DAT(206,"undefined curve")
DAT(206,ENERR_UNDEF_CURVE,"function call refers to undefined curve") DAT(207,"attempt to control CV/GPV link")
DAT(207,ENERR_CANT_CONTROL_CV,"function call attempts to control a CV") 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") // These errors apply to network consistency check
DAT(209,ENERR_ILLEGAL_VAL_NODE,"illegal value for Node") DAT(223,"not enough nodes in network")
DAT(210,ENERR_SPEC_UNDEF_LINK,"specified for undefined Link") DAT(224,"no tanks or reservoirs in network")
DAT(211,ENERR_ILLEGAL_VAL_LINK,"illegal value for Link") DAT(225,"invalid lower/upper levels for tank")
DAT(212,ENERR_TRACE_NODE,"invalid trace node") DAT(226,"no head curve or power rating for pump")
DAT(213,ENERR_ILLEGAL_OPT,"illegal option value in section") DAT(227,"invalid head curve for pump")
DAT(214,ENERR_TOO_MANY_CHAR,"following line of section contains too many characters") DAT(230,"nonincreasing x-values for curve")
DAT(215,ENERR_DUPLICATE_ID,"duplicate ID") DAT(233,"network has unconnected node")
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 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 Authors: see AUTHORS
Copyright: see AUTHORS Copyright: see AUTHORS
License: see LICENSE 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; int i, j, n = 0;
double a; double a;
int errcode = 0, levelerr; int errcode = 0, levelerr;
char errmsg[MAXMSG+1] = "";
Stank *tank; Stank *tank;
Scurve *curve; Scurve *curve;
@@ -383,14 +384,6 @@ int inittanks(Project *pr)
levelerr = 1; 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 else
{ {
// Find min., max., and initial volumes from curve // Find min., max., and initial volumes from curve
@@ -403,6 +396,15 @@ int inittanks(Project *pr)
tank->A = sqrt(4.0 * a / PI); 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; return errcode;
} }

View File

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

View File

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

View File

@@ -7,7 +7,7 @@
Authors: see AUTHORS Authors: see AUTHORS
Copyright: see AUTHORS Copyright: see AUTHORS
License: see LICENSE 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 */ switch (errcode)
//#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;
//#define DAT(code,string) case code: sprintf(msg, "%s", string); break;
#define DAT(code,string) case code: strcpy(msg, string); break;
#include "errors.dat" #include "errors.dat"
#undef DAT #undef DAT
default: default:
strcpy(msg, ""); strcpy(msg, "");
} }
@@ -810,13 +813,15 @@ void errmsg(Project *pr, int errcode)
**---------------------------------------------------------------- **----------------------------------------------------------------
*/ */
{ {
char errmsg[MAXMSG + 1] = "";
if (errcode == 309) /* Report file write error - */ if (errcode == 309) /* Report file write error - */
{ /* Do not write msg to file. */ { /* 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 Authors: see AUTHORS
Copyright: see AUTHORS Copyright: see AUTHORS
License: see LICENSE License: see LICENSE
Last Updated: 11/27/2018 Last Updated: 12/15/2018
****************************************************************************** ******************************************************************************
*/ */
@@ -565,7 +565,8 @@ typedef struct {
MaxPats, // Pattern count " " " MaxPats, // Pattern count " " "
MaxCurves, // Curve count " " " MaxCurves, // Curve count " " "
Ntokens, // Number of tokens in line of input 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 STmplist
*Patlist, // Temporary time pattern list *Patlist, // Temporary time pattern list