Add EN_openX function
EN_openX allows an EPANET input file to be opened even if it has errors. This required re-arranging code, mainly in input3.c, so that default values are assigned to an object before its input line is parsed.
This commit is contained in:
649
src/input3.c
649
src/input3.c
@@ -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: 09/11/2023
|
||||
Last Updated: 09/28/2023
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -27,15 +27,15 @@ extern char *Fldname[];
|
||||
extern char *DemandModelTxt[];
|
||||
extern char *BackflowTxt[];
|
||||
|
||||
// Exported functions
|
||||
int powercurve(double, double, double, double, double, double *, double *,
|
||||
double *);
|
||||
|
||||
// Imported Functions
|
||||
extern int addnodeID(Network *, int, char *);
|
||||
extern int addlinkID(Network *, int, char *);
|
||||
extern int getunitsoption(Project *, char *);
|
||||
extern int getheadlossoption(Project *, char *);
|
||||
|
||||
// Local functions
|
||||
static double gettokvalue(Project *, double, int, int *, int *);
|
||||
static int getlinknodes(Project *, int *, int *);
|
||||
static int optionchoice(Project *, int);
|
||||
static int optionvalue(Project *, int);
|
||||
static int getpumpcurve(Project *, int);
|
||||
@@ -77,31 +77,52 @@ int juncdata(Project *pr)
|
||||
int p = 0; // time pattern index
|
||||
int n; // number of tokens
|
||||
int njuncs; // number of network junction nodes
|
||||
double el, // elevation
|
||||
y = 0.0; // base demand
|
||||
double el = 0.0, // elevation
|
||||
d = 0.0, // base demand
|
||||
x;
|
||||
Snode *node;
|
||||
int err = 0;
|
||||
int errcode = 0;
|
||||
int errtok = -1;
|
||||
|
||||
// Add new junction to data base
|
||||
n = parser->Ntokens;
|
||||
if (net->Nnodes == parser->MaxNodes) return 200;
|
||||
errcode = addnodeID(net, net->Njuncs + 1, parser->Tok[0]);
|
||||
if (errcode > 0) return setError(parser, 0, errcode);
|
||||
net->Njuncs++;
|
||||
net->Nnodes++;
|
||||
njuncs = net->Njuncs;
|
||||
err = addnodeID(net, net->Njuncs, parser->Tok[0]);
|
||||
if (err) return setError(parser, 0, err);
|
||||
|
||||
// Check for valid data
|
||||
if (n < 2) return 201;
|
||||
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)
|
||||
n = parser->Ntokens;
|
||||
if (n > 1)
|
||||
{
|
||||
if (!getfloat(parser->Tok[1], &x))
|
||||
{
|
||||
errcode = 202;
|
||||
errtok = 1;
|
||||
}
|
||||
else el = x;
|
||||
}
|
||||
if (!errcode && n > 2)
|
||||
{
|
||||
if (!getfloat(parser->Tok[2], &x))
|
||||
{
|
||||
errcode = 202;
|
||||
errtok = 2;
|
||||
}
|
||||
else d = x;
|
||||
}
|
||||
if (!errcode && n > 3)
|
||||
{
|
||||
p = findpattern(net, parser->Tok[3]);
|
||||
if (p < 0) return setError(parser, 3, 205);
|
||||
if (p < 0)
|
||||
{
|
||||
errcode = 205;
|
||||
errtok = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// Save junction data
|
||||
njuncs = net->Njuncs;
|
||||
node = &net->Node[njuncs];
|
||||
node->X = MISSING;
|
||||
node->Y = MISSING;
|
||||
@@ -116,11 +137,14 @@ int juncdata(Project *pr)
|
||||
|
||||
// Create a demand for the junction and use NodeDemand as an indicator
|
||||
// to be used when processing demands from the [DEMANDS] section
|
||||
if (!adddemand(node, y, p, NULL)) return 101;
|
||||
hyd->NodeDemand[njuncs] = y;
|
||||
if (!adddemand(node, d, p, NULL)) return 101;
|
||||
hyd->NodeDemand[njuncs] = d;
|
||||
|
||||
// Return error code
|
||||
if (errcode > 0) return setError(parser, errtok, errcode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tankdata(Project *pr)
|
||||
/*
|
||||
**--------------------------------------------------------------
|
||||
@@ -131,7 +155,6 @@ int tankdata(Project *pr)
|
||||
** [RESERVOIRS]
|
||||
** id elev (pattern)
|
||||
** [TANKS]
|
||||
** id elev (pattern)
|
||||
** id elev initlevel minlevel maxlevel diam (minvol vcurve)
|
||||
**--------------------------------------------------------------
|
||||
*/
|
||||
@@ -155,68 +178,84 @@ int tankdata(Project *pr)
|
||||
Snode *node;
|
||||
Stank *tank;
|
||||
|
||||
int err = 0;
|
||||
int errcode = 0;
|
||||
int errtok = -1;
|
||||
double x;
|
||||
|
||||
// Add new tank to data base
|
||||
n = parser->Ntokens;
|
||||
if (net->Ntanks == parser->MaxTanks ||
|
||||
net->Nnodes == parser->MaxNodes) return 200;
|
||||
i = parser->MaxJuncs + net->Ntanks + 1;
|
||||
errcode = addnodeID(net, i, parser->Tok[0]);
|
||||
if (errcode) return setError(parser, 0, errcode);
|
||||
net->Ntanks++;
|
||||
net->Nnodes++;
|
||||
|
||||
i = parser->MaxJuncs + net->Ntanks;
|
||||
err = addnodeID(net, i, parser->Tok[0]);
|
||||
if (err) return setError(parser, 0, err);
|
||||
|
||||
// Check for valid data
|
||||
if (n < 2) return 201;
|
||||
if (!getfloat(parser->Tok[1], &el)) return setError(parser, 1, 202);
|
||||
n = parser->Ntokens;
|
||||
if (n < 2) errcode = 201;
|
||||
if (!errcode && !getfloat(parser->Tok[1], &x))
|
||||
{
|
||||
errcode = 202;
|
||||
errtok = 1;
|
||||
}
|
||||
else el = x;
|
||||
|
||||
// Tank is reservoir
|
||||
// Node is a reservoir
|
||||
if (n <= 3)
|
||||
{
|
||||
// Head pattern supplied
|
||||
if (n == 3)
|
||||
if (n == 3 && !errcode)
|
||||
{
|
||||
pattern = findpattern(net, parser->Tok[2]);
|
||||
if (pattern < 0) return setError(parser, 2, 205);
|
||||
}
|
||||
}
|
||||
else if (n < 6) return 201;
|
||||
|
||||
// Tank is a storage tank
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (strlen(parser->Tok[7]) > 0 && *(parser->Tok[7]) != '*')
|
||||
if (pattern < 0)
|
||||
{
|
||||
curve = findcurve(net, parser->Tok[7]);
|
||||
if (curve == 0) return setError(parser, 7, 206);
|
||||
net->Curve[curve].Type = VOLUME_CURVE;
|
||||
errcode = 205;
|
||||
errtok = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse overflow indicator if present
|
||||
if (n >= 9)
|
||||
}
|
||||
|
||||
// Node is a storage tank
|
||||
else if (!errcode)
|
||||
{
|
||||
if (n < 6) errcode = 201;
|
||||
else
|
||||
{
|
||||
if (match(parser->Tok[8], w_YES)) overflow = TRUE;
|
||||
else if (match(parser->Tok[8], w_NO)) overflow = FALSE;
|
||||
else return setError(parser, 8, 213);
|
||||
}
|
||||
// Read required data
|
||||
initlevel = gettokvalue(pr, initlevel, 2, &errcode, &errtok);
|
||||
minlevel = gettokvalue(pr, minlevel, 3, &errcode, &errtok);
|
||||
maxlevel = gettokvalue(pr, maxlevel, 4, &errcode, &errtok);
|
||||
diam = gettokvalue(pr, diam, 5, &errcode, &errtok);
|
||||
if (n >= 7) minvol = gettokvalue(pr, minvol, 6, &errcode, &errtok);
|
||||
|
||||
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);
|
||||
// If volume curve supplied check it exists
|
||||
if (!errcode && n >= 8)
|
||||
{
|
||||
if (strlen(parser->Tok[7]) > 0 && *(parser->Tok[7]) != '*')
|
||||
{
|
||||
curve = findcurve(net, parser->Tok[7]);
|
||||
if (curve == 0)
|
||||
{
|
||||
errcode = 206;
|
||||
errtok = 7;
|
||||
}
|
||||
else net->Curve[curve].Type = VOLUME_CURVE;
|
||||
}
|
||||
}
|
||||
|
||||
// Read overflow indicator if present
|
||||
if (!errcode && n >= 9)
|
||||
{
|
||||
if (match(parser->Tok[8], w_YES)) overflow = TRUE;
|
||||
else if (match(parser->Tok[8], w_NO)) overflow = FALSE;
|
||||
else
|
||||
{
|
||||
errcode = 213;
|
||||
errtok = 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
node = &net->Node[i];
|
||||
tank = &net->Tank[net->Ntanks];
|
||||
@@ -254,9 +293,38 @@ int tankdata(Project *pr)
|
||||
tank->Vcurve = curve;
|
||||
tank->MixModel = MIX1; // Completely mixed
|
||||
tank->V1frac = 1.0; // Mixing compartment size fraction
|
||||
|
||||
// Return error code
|
||||
if (errcode > 0) return setError(parser, errtok, errcode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
double gettokvalue(Project *pr, double x, int itok, int *errcode, int *errtok)
|
||||
/*
|
||||
**--------------------------------------------------------------
|
||||
** Input: x = default numerical value
|
||||
** itok = index into an array of string tokens
|
||||
** Output: errcode = an error code or 0 if successful
|
||||
** errtok = itok if an error occurs
|
||||
** returns a numerical data value
|
||||
** Purpose: converts a string token into a numerical value.
|
||||
**--------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
Parser *parser = &pr->parser;
|
||||
double result;
|
||||
|
||||
if (*errcode) return x;
|
||||
if (!getfloat(parser->Tok[itok], &result)) *errcode = 202;
|
||||
else if (result < 0.0) *errcode = 209;
|
||||
if (*errcode > 0)
|
||||
{
|
||||
result = x;
|
||||
*errtok = itok;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int pipedata(Project *pr)
|
||||
/*
|
||||
**--------------------------------------------------------------
|
||||
@@ -275,71 +343,101 @@ int pipedata(Project *pr)
|
||||
int j1, // Start-node index
|
||||
j2, // End-node index
|
||||
n; // # data items
|
||||
double length, // Pipe length
|
||||
diam, // Pipe diameter
|
||||
rcoeff, // Roughness coeff.
|
||||
lcoeff = 0.0; // Minor loss coeff
|
||||
LinkType type = PIPE; // Link type
|
||||
StatusType status = OPEN; // Link status
|
||||
double x;
|
||||
Slink *link;
|
||||
int err = 0;
|
||||
|
||||
// Add new pipe to data base
|
||||
n = parser->Ntokens;
|
||||
int errcode = 0;
|
||||
|
||||
// Check that end nodes exist
|
||||
if (net->Nlinks == parser->MaxLinks) return 200;
|
||||
net->Npipes++;
|
||||
net->Nlinks++;
|
||||
err = addlinkID(net, net->Nlinks, parser->Tok[0]);
|
||||
if (err) return setError(parser, 0, err);
|
||||
|
||||
// Check for valid data
|
||||
if (n < 6) return 201;
|
||||
n = parser->Ntokens;
|
||||
if (n < 3) return setError(parser, -1, errcode);
|
||||
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)) 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) return setError(parser, 5, 211);
|
||||
// Add new pipe to data base
|
||||
errcode = addlinkID(net, net->Nlinks+1, parser->Tok[0]);
|
||||
if (errcode) return setError(parser, 0, errcode);
|
||||
net->Npipes++;
|
||||
net->Nlinks++;
|
||||
|
||||
// Either a loss coeff. or a status is supplied
|
||||
if (n == 7)
|
||||
{
|
||||
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 setError(parser, 6, 202);
|
||||
}
|
||||
|
||||
// Both a loss coeff. and a status is supplied
|
||||
if (n == 8)
|
||||
{
|
||||
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 setError(parser, 7, 213);
|
||||
}
|
||||
if (lcoeff < 0.0) return setError(parser, 6, 211);
|
||||
|
||||
// Save pipe data
|
||||
// Assign default data to pipe
|
||||
link = &net->Link[net->Nlinks];
|
||||
link->N1 = j1;
|
||||
link->N2 = j2;
|
||||
link->Len = length;
|
||||
link->Diam = diam;
|
||||
link->Kc = rcoeff;
|
||||
link->Km = lcoeff;
|
||||
|
||||
if (parser->Unitsflag == SI)
|
||||
{
|
||||
link->Len = 100.0;
|
||||
link->Diam = 254.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
link->Len = 330.0;
|
||||
link->Diam = 10.0;
|
||||
}
|
||||
switch (pr->hydraul.Formflag)
|
||||
{
|
||||
case HW: link->Kc = 130; break;
|
||||
case DW: link->Kc = 0.0005; break;
|
||||
case CM: link->Kc = 0.01; break;
|
||||
default: link->Kc = 1.0;
|
||||
}
|
||||
|
||||
link->Km = 0.0;
|
||||
link->Kb = MISSING;
|
||||
link->Kw = MISSING;
|
||||
link->Type = type;
|
||||
link->Status = status;
|
||||
link->Type = PIPE;
|
||||
link->Status = OPEN;
|
||||
link->Rpt = 0;
|
||||
link->ResultIndex = 0;
|
||||
link->Comment = xstrcpy(&link->Comment, parser->Comment, MAXMSG);
|
||||
|
||||
// Parse data values from input tokens
|
||||
if (n > 3)
|
||||
{
|
||||
if (!getfloat(parser->Tok[3], &x) || x <= 0.0)
|
||||
return setError(parser, 3, 202);
|
||||
link->Len = x;
|
||||
}
|
||||
if (n > 4)
|
||||
{
|
||||
if (!getfloat(parser->Tok[4], &x) || x <= 0.0)
|
||||
return setError(parser, 4, 202);
|
||||
link->Diam = x;
|
||||
}
|
||||
if (n > 5)
|
||||
{
|
||||
if (!getfloat(parser->Tok[5], &x) || x <= 0.0)
|
||||
return setError(parser, 5, 202);
|
||||
link->Kc = x;
|
||||
}
|
||||
|
||||
// Either a loss coeff. or a status is supplied
|
||||
if (n > 6)
|
||||
{
|
||||
if (match(parser->Tok[6], w_CV)) link->Type = CVPIPE;
|
||||
else if (match(parser->Tok[6], w_CLOSED)) link->Status = CLOSED;
|
||||
else if (match(parser->Tok[6], w_OPEN)) link->Status = OPEN;
|
||||
else
|
||||
{
|
||||
if (!getfloat(parser->Tok[6], &x) || x < 0.0)
|
||||
return setError(parser, 6, 202);
|
||||
link->Km = x;
|
||||
}
|
||||
}
|
||||
|
||||
// Both a loss coeff. and a status is supplied
|
||||
if (n > 7)
|
||||
{
|
||||
if (!getfloat(parser->Tok[6], &x) || x < 0.0)
|
||||
return setError(parser, 6, 202);
|
||||
link->Km = x;
|
||||
if (match(parser->Tok[7], w_CV)) link->Type = CVPIPE;
|
||||
else if (match(parser->Tok[7], w_CLOSED)) link->Status = CLOSED;
|
||||
else if (match(parser->Tok[7], w_OPEN)) link->Status = OPEN;
|
||||
else return setError(parser, 7, 213);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -351,11 +449,6 @@ int pumpdata(Project *pr)
|
||||
** Purpose: processes pump data
|
||||
** Formats:
|
||||
** [PUMP]
|
||||
** (Version 1.x Format):
|
||||
** id node1 node2 power
|
||||
** id node1 node2 h1 q1
|
||||
** id node1 node2 h0 h1 q1 h2 q2
|
||||
** (Version 2 Format):
|
||||
** id node1 node2 KEYWORD value {KEYWORD value ...}
|
||||
** where KEYWORD = [POWER,HEAD,PATTERN,SPEED]
|
||||
**--------------------------------------------------------------
|
||||
@@ -364,7 +457,7 @@ int pumpdata(Project *pr)
|
||||
Network *net = &pr->network;
|
||||
Parser *parser = &pr->parser;
|
||||
|
||||
int j, m, // Token array indexes
|
||||
int m, // Token array indexes
|
||||
j1, // Start-node index
|
||||
j2, // End-node index
|
||||
n, // # data items
|
||||
@@ -372,24 +465,24 @@ int pumpdata(Project *pr)
|
||||
double y;
|
||||
Slink *link;
|
||||
Spump *pump;
|
||||
int err = 0;
|
||||
|
||||
/* Add new pump to data base */
|
||||
n = parser->Ntokens;
|
||||
int errcode = 0;
|
||||
|
||||
// Check that end nodes exist
|
||||
if (net->Nlinks == parser->MaxLinks ||
|
||||
net->Npumps == parser->MaxPumps) return 200;
|
||||
net->Nlinks++;
|
||||
net->Npumps++;
|
||||
err = addlinkID(net, net->Nlinks, parser->Tok[0]);
|
||||
if (err) return setError(parser, 0, err);
|
||||
|
||||
// Check for valid data
|
||||
if (n < 3) return 201;
|
||||
n = parser->Ntokens;
|
||||
if (n < 3) return setError(parser, -1, errcode);
|
||||
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
|
||||
// Add new pump to data base
|
||||
errcode = addlinkID(net, net->Nlinks+1, parser->Tok[0]);
|
||||
if (errcode) return setError(parser, 0, errcode);
|
||||
net->Nlinks++;
|
||||
net->Npumps++;
|
||||
|
||||
// Assign default data to pump
|
||||
link = &net->Link[net->Nlinks];
|
||||
pump = &net->Pump[net->Npumps];
|
||||
|
||||
@@ -415,28 +508,14 @@ int pumpdata(Project *pr)
|
||||
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
|
||||
if (getfloat(parser->Tok[3], &parser->X[0]))
|
||||
{
|
||||
m = 1;
|
||||
for (j = 4; j < n; j++)
|
||||
{
|
||||
if (!getfloat(parser->Tok[j], &parser->X[m])) return setError(parser, j, 202);
|
||||
m++;
|
||||
}
|
||||
return (getpumpcurve(pr, m));
|
||||
}
|
||||
|
||||
// Otherwise input follows Version 2 format
|
||||
// so retrieve keyword/value pairs
|
||||
// Retrieve keyword/value pairs
|
||||
m = 4;
|
||||
while (m < n)
|
||||
{
|
||||
if (match(parser->Tok[m - 1], w_POWER)) // Const. HP curve
|
||||
{
|
||||
y = atof(parser->Tok[m]);
|
||||
if (y <= 0.0) return setError(parser, m, 202);
|
||||
if (!getfloat(parser->Tok[m], &y) || y <= 0.0)
|
||||
return setError(parser, m, 202);
|
||||
pump->Ptype = CONST_HP;
|
||||
link->Km = y;
|
||||
}
|
||||
@@ -454,11 +533,11 @@ int pumpdata(Project *pr)
|
||||
}
|
||||
else if (match(parser->Tok[m - 1], w_SPEED)) // Speed setting
|
||||
{
|
||||
if (!getfloat(parser->Tok[m], &y)) return setError(parser, m, 202);
|
||||
if (y < 0.0) return setError(parser, m, 211);
|
||||
if (!getfloat(parser->Tok[m], &y) || y < 0.0)
|
||||
return setError(parser, m, 202);
|
||||
link->Kc = y;
|
||||
}
|
||||
else return 201;
|
||||
else return setError(parser, m-1, 201);;
|
||||
m = m + 2; // Move to next keyword token
|
||||
}
|
||||
return 0;
|
||||
@@ -485,74 +564,30 @@ int valvedata(Project *pr)
|
||||
n; // # data items
|
||||
char status = ACTIVE, // Valve status
|
||||
type; // Valve type
|
||||
double diam = 0.0, // Valve diameter
|
||||
setting, // Valve setting
|
||||
lcoeff = 0.0; // Minor loss coeff.
|
||||
double x;
|
||||
Slink *link;
|
||||
int err = 0,
|
||||
int errcode = 0,
|
||||
losscurve = 0; // Loss coeff. curve
|
||||
|
||||
// Add new valve to data base
|
||||
n = parser->Ntokens;
|
||||
// Check that end nodes exist
|
||||
if (net->Nlinks == parser->MaxLinks ||
|
||||
net->Nvalves == parser->MaxValves) return 200;
|
||||
net->Nvalves++;
|
||||
net->Nlinks++;
|
||||
err = addlinkID(net, net->Nlinks, parser->Tok[0]);
|
||||
if (err) return setError(parser, 0, err);
|
||||
|
||||
// Check for valid data
|
||||
if (n < 6)
|
||||
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);
|
||||
|
||||
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_PBV))
|
||||
type = PBV;
|
||||
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 if (match(parser->Tok[4], w_PCV))
|
||||
type = PCV;
|
||||
else
|
||||
return setError(parser, 4, 213);
|
||||
|
||||
if (!getfloat(parser->Tok[3], &diam)) return setError(parser, 3, 202);
|
||||
if (diam <= 0.0) return setError(parser, 3, 211);
|
||||
|
||||
// Find headloss curve for GPV
|
||||
if (type == GPV)
|
||||
{
|
||||
c = findcurve(net, parser->Tok[5]);
|
||||
if (c == 0) return setError(parser, 5, 206);
|
||||
setting = c;
|
||||
net->Curve[c].Type = HLOSS_CURVE;
|
||||
status = OPEN;
|
||||
}
|
||||
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);
|
||||
n = parser->Ntokens;
|
||||
if (n < 5) return setError(parser, -1, errcode);
|
||||
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);
|
||||
|
||||
// Parse valve type
|
||||
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_PBV)) type = PBV;
|
||||
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 if (match(parser->Tok[4], w_PCV)) type = PCV;
|
||||
else return setError(parser, 4, 213);
|
||||
|
||||
// Find loss coeff. curve for PCV
|
||||
if (type == PCV && n >= 8)
|
||||
{
|
||||
c = findcurve(net, parser->Tok[7]);
|
||||
if (c == 0) return setError(parser, 7, 206);
|
||||
losscurve = c;
|
||||
net->Curve[c].Type = VALVE_CURVE;
|
||||
if (setting > 100.0) setting = 100.0;
|
||||
}
|
||||
|
||||
// Check for illegal connections
|
||||
if (valvecheck(pr, net->Nlinks, type, j1, j2))
|
||||
{
|
||||
@@ -561,23 +596,67 @@ int valvedata(Project *pr)
|
||||
else return setError(parser, -1, 220);
|
||||
}
|
||||
|
||||
// Save valve data
|
||||
// Add new valve to data base
|
||||
errcode = addlinkID(net, net->Nlinks+1, parser->Tok[0]);
|
||||
if (errcode) return setError(parser, 0, errcode);
|
||||
net->Nvalves++;
|
||||
net->Nlinks++;
|
||||
|
||||
// Assign default data to valve
|
||||
link = &net->Link[net->Nlinks];
|
||||
link->N1 = j1;
|
||||
link->N2 = j2;
|
||||
link->Diam = diam;
|
||||
if (parser->Unitsflag == SI) link->Diam = 254.0;
|
||||
else link->Diam = 10.0;
|
||||
link->Len = 0.0;
|
||||
link->Kc = setting;
|
||||
link->Km = lcoeff;
|
||||
link->Kc = 0.0;
|
||||
link->Km = 0.0;
|
||||
link->Kb = 0.0;
|
||||
link->Kw = 0.0;
|
||||
link->Type = type;
|
||||
link->Status = status;
|
||||
link->Status = ACTIVE;
|
||||
link->Rpt = 0;
|
||||
link->ResultIndex = 0;
|
||||
link->Comment = xstrcpy(&link->Comment, parser->Comment, MAXMSG);
|
||||
net->Valve[net->Nvalves].Link = net->Nlinks;
|
||||
net->Valve[net->Nvalves].Curve = losscurve;
|
||||
net->Valve[net->Nvalves].Curve = 0;
|
||||
|
||||
// Parse data values
|
||||
if (!getfloat(parser->Tok[3], &x) || x <= 0.0)
|
||||
return setError(parser, 3, 202);
|
||||
link->Diam = x;
|
||||
if (n > 5)
|
||||
{
|
||||
// Find headloss curve for GPV
|
||||
if (type == GPV)
|
||||
{
|
||||
c = findcurve(net, parser->Tok[5]);
|
||||
if (c == 0) return setError(parser, 5, 206);
|
||||
link->Kc = c;
|
||||
net->Curve[c].Type = HLOSS_CURVE;
|
||||
link->Status = OPEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!getfloat(parser->Tok[5], &x)) return setError(parser, 5, 202);
|
||||
link->Kc = x;
|
||||
}
|
||||
}
|
||||
if (n > 6)
|
||||
{
|
||||
if (!getfloat(parser->Tok[6], &x) || x < 0.0)
|
||||
return setError(parser, 6, 202);
|
||||
link->Km = x;
|
||||
}
|
||||
if (n > 7 && type == PCV)
|
||||
{
|
||||
// Find loss coeff. curve for PCV
|
||||
c = findcurve(net, parser->Tok[7]);
|
||||
if (c == 0) return setError(parser, 7, 206);
|
||||
net->Valve[net->Nvalves].Curve = c;
|
||||
net->Curve[c].Type = VALVE_CURVE;
|
||||
if (link->Kc > 100.0) link->Kc = 100.0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -628,6 +707,7 @@ int patterndata(Project *pr)
|
||||
pattern->F = realloc(pattern->F, pattern->Length * sizeof(double));
|
||||
|
||||
// Add parsed multipliers to the pattern
|
||||
for (j = 1; j <= n; j++) pattern->F[n1 + j - 1] = 1.0;
|
||||
for (j = 1; j <= n; j++)
|
||||
{
|
||||
if (!getfloat(parser->Tok[j], &x)) return setError(parser, j, 202);
|
||||
@@ -776,7 +856,6 @@ int demanddata(Project *pr)
|
||||
** Purpose: processes node demand data
|
||||
** Format:
|
||||
** [DEMANDS]
|
||||
** MULTIPLY factor
|
||||
** node base_demand (pattern)
|
||||
**
|
||||
** NOTE: Demands entered in this section replace those
|
||||
@@ -798,15 +877,7 @@ int demanddata(Project *pr)
|
||||
if (n < 2) return 201;
|
||||
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 setError(parser, 1, 213);
|
||||
else hyd->Dmult = y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Otherwise find node (and pattern) being referenced
|
||||
// Find node (and pattern) being referenced
|
||||
if ((j = findnode(net, parser->Tok[0])) == 0) return setError(parser, 0, 203);
|
||||
if (j > net->Njuncs) return 0;
|
||||
if (n >= 3)
|
||||
@@ -1781,25 +1852,14 @@ int optionchoice(Project *pr, int n)
|
||||
if (match(parser->Tok[0], w_UNITS))
|
||||
{
|
||||
if (n < 1) return 0;
|
||||
else if (match(parser->Tok[1], w_CFS)) parser->Flowflag = CFS;
|
||||
else if (match(parser->Tok[1], w_GPM)) parser->Flowflag = GPM;
|
||||
else if (match(parser->Tok[1], w_AFD)) parser->Flowflag = AFD;
|
||||
else if (match(parser->Tok[1], w_MGD)) parser->Flowflag = MGD;
|
||||
else if (match(parser->Tok[1], w_IMGD)) parser->Flowflag = IMGD;
|
||||
else if (match(parser->Tok[1], w_LPS)) parser->Flowflag = LPS;
|
||||
else if (match(parser->Tok[1], w_LPM)) parser->Flowflag = LPM;
|
||||
else if (match(parser->Tok[1], w_CMH)) parser->Flowflag = CMH;
|
||||
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_CMS)) parser->Flowflag = CMS;
|
||||
else if (match(parser->Tok[1], w_SI)) parser->Flowflag = LPS;
|
||||
else return setError(parser, 1, 213);
|
||||
if (!getunitsoption(pr, parser->Tok[1]))
|
||||
return setError(parser, 1, 213);
|
||||
}
|
||||
|
||||
// PRESSURE units
|
||||
else if (match(parser->Tok[0], w_PRESSURE))
|
||||
{
|
||||
if (n < 1) return 0;
|
||||
if (n < 1) return 0;
|
||||
else if (match(parser->Tok[1], w_EXPONENT)) return -1;
|
||||
else if (match(parser->Tok[1], w_PSI)) parser->Pressflag = PSI;
|
||||
else if (match(parser->Tok[1], w_KPA)) parser->Pressflag = KPA;
|
||||
@@ -1811,10 +1871,8 @@ int optionchoice(Project *pr, int n)
|
||||
else if (match(parser->Tok[0], w_HEADLOSS))
|
||||
{
|
||||
if (n < 1) return 0;
|
||||
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 setError(parser, 1, 213);
|
||||
if (!getheadlossoption(pr, parser->Tok[1]))
|
||||
return setError(parser, 1, 213);
|
||||
}
|
||||
|
||||
// HYDRUALICS USE/SAVE file option
|
||||
@@ -2063,101 +2121,6 @@ int optionvalue(Project *pr, int n)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getpumpcurve(Project *pr, int n)
|
||||
/*
|
||||
**--------------------------------------------------------
|
||||
** Input: n = number of parameters for pump curve
|
||||
** Output: returns error code
|
||||
** Purpose: processes pump curve data for Version 1.1-
|
||||
** style input data
|
||||
** Notes:
|
||||
** 1. Called by pumpdata() in INPUT3.C
|
||||
** 2. Current link index & pump index of pump being
|
||||
** processed is found in network variables Nlinks
|
||||
** and Npumps, respectively
|
||||
** 3. Curve data read from input line is found in
|
||||
** parser's array X[0],...X[n-1]
|
||||
**---------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
Network *net = &pr->network;
|
||||
Parser *parser = &pr->parser;
|
||||
|
||||
double a, b, c, h0, h1, h2, q1, q2;
|
||||
Spump *pump = &net->Pump[net->Npumps];
|
||||
|
||||
// Constant HP curve
|
||||
if (n == 1)
|
||||
{
|
||||
if (parser->X[0] <= 0.0) return 202;
|
||||
pump->Ptype = CONST_HP;
|
||||
net->Link[net->Nlinks].Km = parser->X[0];
|
||||
}
|
||||
|
||||
// Power function curve
|
||||
else
|
||||
{
|
||||
// Single point power curve
|
||||
if (n == 2)
|
||||
{
|
||||
q1 = parser->X[1];
|
||||
h1 = parser->X[0];
|
||||
h0 = 1.33334 * h1;
|
||||
q2 = 2.0 * q1;
|
||||
h2 = 0.0;
|
||||
}
|
||||
|
||||
// 3-point power curve
|
||||
else if (n >= 5)
|
||||
{
|
||||
h0 = parser->X[0];
|
||||
h1 = parser->X[1];
|
||||
q1 = parser->X[2];
|
||||
h2 = parser->X[3];
|
||||
q2 = parser->X[4];
|
||||
}
|
||||
else return 202;
|
||||
pump->Ptype = POWER_FUNC;
|
||||
if (!powercurve(h0, h1, h2, q1, q2, &a, &b, &c)) return 206;
|
||||
pump->H0 = -a;
|
||||
pump->R = -b;
|
||||
pump->N = c;
|
||||
pump->Q0 = q1;
|
||||
pump->Qmax = pow((-a / b), (1.0 / c));
|
||||
pump->Hmax = h0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int powercurve(double h0, double h1, double h2, double q1, double q2,
|
||||
double *a, double *b, double *c)
|
||||
/*
|
||||
**---------------------------------------------------------
|
||||
** Input: h0 = shutoff head
|
||||
** h1 = design head
|
||||
** h2 = head at max. flow
|
||||
** q1 = design flow
|
||||
** q2 = max. flow
|
||||
** Output: *a, *b, *c = pump curve coeffs. (H = a-bQ^c),
|
||||
** Returns 1 if sucessful, 0 otherwise.
|
||||
** Purpose: computes coeffs. for pump curve
|
||||
**----------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
double h4, h5;
|
||||
|
||||
if (h0 < TINY || h0 - h1 < TINY || h1 - h2 < TINY ||
|
||||
q1 < TINY || q2 - q1 < TINY
|
||||
) return 0;
|
||||
*a = h0;
|
||||
h4 = h0 - h1;
|
||||
h5 = h0 - h2;
|
||||
*c = log(h5 / h4) / log(q2 / q1);
|
||||
if (*c <= 0.0 || *c > 20.0) return 0;
|
||||
*b = -h4 / pow(q1, *c);
|
||||
if (*b >= 0.0) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void changestatus(Network *net, int j, StatusType status, double y)
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user