Merge pull request #450 from OpenWaterAnalytics/lrossman-dev

Eliminates use of temporary linked lists to process Patterns & Curves…
This commit is contained in:
Lew Rossman
2019-04-08 11:08:34 -04:00
committed by GitHub
7 changed files with 296 additions and 449 deletions

View File

@@ -172,10 +172,7 @@ int DLLEXPORT EN_init(EN_Project p, const char *rptFile, const char *outFile,
initunits(p);
inittanks(p);
convertunits(p);
// Initialize the default demand pattern
p->parser.MaxPats = 0;
getpatterns(p);
p->Openflag = TRUE;
return errcode;
}
@@ -230,10 +227,6 @@ int DLLEXPORT EN_open(EN_Project p, const char *inpFile, const char *rptFile,
p->parser.InFile = NULL;
}
// Free temporary linked lists used for Patterns & Curves
freeTmplist(p->parser.Patlist);
freeTmplist(p->parser.Curvelist);
// If using previously saved hydraulics file then open it
if (p->outfile.Hydflag == USE) ERRCODE(openhydfile(p));
@@ -3943,7 +3936,6 @@ int DLLEXPORT EN_addpattern(EN_Project p, char *id)
{
Network *net = &p->network;
Parser *parser = &p->parser;
Hydraul *hyd = &p->hydraul;
int i, n, err = 0;
Spattern *pat;
@@ -4231,6 +4223,7 @@ int DLLEXPORT EN_addcurve(EN_Project p, char *id)
curve = &net->Curve[n];
strcpy(curve->ID, id);
curve->Comment = NULL;
curve->Capacity = 1;
curve->Npts = 1;
curve->Type = GENERIC_CURVE;
curve->X = (double *)calloc(1, sizeof(double));
@@ -4302,20 +4295,11 @@ int DLLEXPORT EN_getcurveindex(EN_Project p, char *id, int *index)
**----------------------------------------------------------------
*/
{
int i;
*index = 0;
if (!p->Openflag) return 102;
for (i = 1; i <= p->network.Ncurves; i++)
{
if (strcmp(id, p->network.Curve[i].ID) == 0)
{
*index = i;
*index = findcurve(&p->network, id);
if (*index == 0) return 206;
return 0;
}
}
*index = 0;
return 206;
}
int DLLEXPORT EN_getcurveid(EN_Project p, int index, char *id)
@@ -4404,8 +4388,8 @@ int DLLEXPORT EN_getcurvevalue(EN_Project p, int curveIndex, int pointIndex,
if (!p->Openflag) return 102;
if (curveIndex < 1 || curveIndex > p->network.Ncurves) return 206;
if (pointIndex < 1 || pointIndex > p->network.Curve[curveIndex].Npts) return 251;
*x = (double)p->network.Curve[curveIndex].X[pointIndex - 1];
*y = (double)p->network.Curve[curveIndex].Y[pointIndex - 1];
*x = p->network.Curve[curveIndex].X[pointIndex - 1];
*y = p->network.Curve[curveIndex].Y[pointIndex - 1];
return 0;
}
@@ -4419,18 +4403,43 @@ int DLLEXPORT EN_setcurvevalue(EN_Project p, int curveIndex, int pointIndex,
** Output: none
** Returns: error code
** Purpose: sets the value of a specific point on a data curve
** Note: if pointIndex exceeds the curve's length a new point is added.
**----------------------------------------------------------------
*/
{
Network *net = &p->network;
Scurve *curve;
double x1 = -1.e37, x2 = 1.e37;
int n = pointIndex - 1;
// Check for valid input
if (!p->Openflag) return 102;
if (curveIndex <= 0 || curveIndex > net->Ncurves) return 206;
curve = &net->Curve[curveIndex];
if (pointIndex <= 0 || pointIndex > curve->Npts) return 251;
curve->X[pointIndex - 1] = x;
curve->Y[pointIndex - 1] = y;
if (pointIndex <= 0) return 251;
// Check that new point maintains increasing x values
if (n - 1 >= 0) x1 = curve->X[n-1];
if (n + 1 < curve->Npts) x2 = curve->X[n+1];
if (x <= x1 || x >= x2) return 230;
// Expand curve if need be
if (pointIndex > curve->Npts) pointIndex = curve->Npts + 1;
if (pointIndex >= curve->Capacity)
{
if (resizecurve(curve, curve->Capacity + 10) > 0) return 101;
}
// Increase curve's number of points if need be
if (pointIndex > curve->Npts)
{
curve->Npts++;
n = curve->Npts - 1;
}
// Insert new point into curve
curve->X[n] = x;
curve->Y[n] = y;
return 0;
}
@@ -4490,15 +4499,12 @@ int DLLEXPORT EN_setcurve(EN_Project p, int index, double *xValues,
// Check that x values are increasing
for (j = 1; j < nPoints; j++) if (xValues[j-1] >= xValues[j]) return 230;
// Re-set number of points & reallocate memory for values
// Expand size of curve's data arrays if need be
curve = &net->Curve[index];
curve->Npts = nPoints;
curve->X = (double *)realloc(curve->X, nPoints * sizeof(double));
curve->Y = (double *)realloc(curve->Y, nPoints * sizeof(double));
if (curve->X == NULL) return 101;
if (curve->Y == NULL) return 101;
if (resizecurve(curve, nPoints) > 0) return 101;
// Load values into curve
curve->Npts = nPoints;
for (j = 0; j < nPoints; j++)
{
curve->X[j] = xValues[j];

View File

@@ -7,7 +7,7 @@
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 03/17/2019
Last Updated: 04/03/2019
******************************************************************************
*/
#ifndef FUNCS_H
@@ -17,8 +17,6 @@
void initpointers(Project *);
int allocdata(Project *);
void freeTmplist(STmplist *);
void freeFloatlist(SFloatlist *);
void freedata(Project *);
int openfiles(Project *, const char *, const char *,const char *);
@@ -36,8 +34,12 @@ int findlink(Network *, char *);
int findtank(Network *, int);
int findvalve(Network *, int);
int findpump(Network *, int);
int findpattern(Network *, char *);
int findcurve(Network *, char *);
void adjustpatterns(Network *, int);
void adjustcurves(Network *, int);
int resizecurve(Scurve *, int);
int getcomment(Network *, int, int, char *);
int setcomment(Network *, int, int, const char *);
@@ -65,8 +67,6 @@ void convertunits(Project *);
int netsize(Project *);
int readdata(Project *);
int updatepumpparams(Project *, int);
int getpatterns(Project *);
int getcurves(Project *);
int findmatch(char *, char *[]);
int match(const char *, const char *);
int gettokens(char *, char **, int, char *);

View File

@@ -331,6 +331,7 @@ void adjustdata(Project *pr)
}
// Use default pattern if none assigned to a demand
parser->DefPat = findpattern(net, parser->DefPatID);
if (parser->DefPat > 0) for (i = 1; i <= net->Nnodes; i++)
{
node = &net->Node[i];

View File

@@ -35,7 +35,6 @@ extern char *SectTxt[]; // Input section keywords (see ENUMSTXT.H)
// Exported functions
int addnodeID(Network *n, int, char *);
int addlinkID(Network *n, int, char *);
STmplist *getlistitem(char *, STmplist *);
// Imported functions
extern int powercurve(double, double, double, double, double, double *,
@@ -43,8 +42,8 @@ extern int powercurve(double, double, double, double, double, double *,
// Local functions
static int newline(Project *, int, char *);
static int addpattern(Parser *, char *);
static int addcurve(Parser *, char *);
static int addpattern(Network *, char *);
static int addcurve(Network *, char *);
static int unlinked(Project *);
static int getpumpparams(Project *);
static void inperrmsg(Project *, int, int, char *);
@@ -65,6 +64,7 @@ int netsize(Project *pr)
char *tok; // First token of line
int sect, newsect; // Input data sections
int errcode = 0; // Error code
Spattern *pattern;
// Initialize object counts
parser->MaxJuncs = 0;
@@ -77,13 +77,20 @@ int netsize(Project *pr)
parser->MaxCurves = 0;
sect = -1;
// Add a default demand pattern
parser->MaxPats = -1;
addpattern(parser,"");
if (parser->InFile == NULL) return 0;
// Add a "dummy" time pattern with index of 0 and a single multiplier
// of 1.0 to be used by all demands not assigned a pattern
pr->network.Npats = -1;
errcode = addpattern(&pr->network, "");
if (errcode) return errcode;
pattern = &pr->network.Pattern[0];
pattern->Length = 1;
pattern[0].F = (double *)calloc(1, sizeof(double));
pattern[0].F[0] = 1.0;
parser->MaxPats = pr->network.Npats;
// Make a pass through input file counting number of each object
if (parser->InFile == NULL) return 0;
while (fgets(line, MAXLINE, parser->InFile) != NULL)
{
// Skip blank lines & those beginning with a comment
@@ -115,8 +122,14 @@ int netsize(Project *pr)
case _VALVES: parser->MaxValves++; break;
case _CONTROLS: parser->MaxControls++; break;
case _RULES: addrule(parser,tok); break;
case _PATTERNS: errcode = addpattern(parser, tok); break;
case _CURVES: errcode = addcurve(parser, tok); break;
case _PATTERNS:
errcode = addpattern(&pr->network, tok);
parser->MaxPats = pr->network.Npats;
break;
case _CURVES:
errcode = addcurve(&pr->network, tok);
parser->MaxCurves = pr->network.Ncurves;
break;
}
if (errcode) break;
}
@@ -166,12 +179,15 @@ int readdata(Project *pr)
net->Nvalves = 0;
net->Ncontrols = 0;
net->Nrules = 0;
net->Ncurves = parser->MaxCurves;
net->Npats = parser->MaxPats;
// Patterns & Curves were created previously in netsize()
parser->MaxPats = net->Npats;
parser->MaxCurves = net->Ncurves;
parser->PrevPat = NULL;
parser->PrevCurve = NULL;
parser->LineComment[0] = '\0';
// Initialize full line comment, input data section and error count
parser->LineComment[0] = '\0';
sect = -1;
errsum = 0;
@@ -257,9 +273,7 @@ int readdata(Project *pr)
// Check for unlinked nodes
if (!errcode) errcode = unlinked(pr);
// Get pattern & curve data from temporary lists
if (!errcode) errcode = getpatterns(pr);
if (!errcode) errcode = getcurves(pr);
// Determine pump curve parameters
if (!errcode) errcode = getpumpparams(pr);
// Free input buffer
@@ -487,7 +501,7 @@ int addlinkID(Network *net, int n, char *id)
return 1;
}
int addpattern(Parser *parser, char *id)
int addpattern(Network *network, char *id)
/*
**-------------------------------------------------------------
** Input: id = pattern ID label
@@ -496,34 +510,33 @@ int addpattern(Parser *parser, char *id)
**--------------------------------------------------------------
*/
{
STmplist *patlist;
int n = network->Npats;
Spattern *pattern;
// Check if ID is same as last one processed
if (parser->Patlist != NULL && strcmp(id, parser->Patlist->ID) == 0) return 0;
// Check that pattern was not already created
if (getlistitem(id, parser->Patlist) == NULL)
// Check if pattern was already created
if (n > 0)
{
// Update pattern count & create new list element
(parser->MaxPats)++;
patlist = (STmplist *)malloc(sizeof(STmplist));
if (patlist == NULL) return 101;
if (strcmp(id, network->Pattern[n].ID) == 0) return 0;
if (findpattern(network, id) > 0) return 0;
}
if (strlen(id) > MAXID) return 250;
// Initialize list element properties
else
{
patlist->i = parser->MaxPats;
strncpy(patlist->ID, id, MAXID);
patlist->x = NULL;
patlist->y = NULL;
patlist->next = parser->Patlist;
parser->Patlist = patlist;
}
}
// Update pattern count & add a new pattern to the database
n = n + 2;
network->Pattern = (Spattern *)realloc(network->Pattern, n * sizeof(Spattern));
if (network->Pattern == NULL) return 101;
(network->Npats)++;
// Initialize the pattern
pattern = &network->Pattern[network->Npats];
strncpy(pattern->ID, id, MAXID);
pattern->Comment = NULL;
pattern->Length = 0;
pattern->F = NULL;
return 0;
}
int addcurve(Parser *parser, char *id)
int addcurve(Network *network, char *id)
/*
**-------------------------------------------------------------
** Input: id = curve ID label
@@ -532,51 +545,34 @@ int addcurve(Parser *parser, char *id)
**--------------------------------------------------------------
*/
{
STmplist *curvelist;
int n = network->Ncurves;
Scurve *curve;
// Check if ID is same as last one processed
if (parser->Curvelist != NULL && strcmp(id, parser->Curvelist->ID) == 0) return 0;
// Check that curve was not already created
if (getlistitem(id, parser->Curvelist) == NULL)
// Check if was already created
if (n > 0)
{
// Update curve count & create new list element
(parser->MaxCurves)++;
curvelist = (STmplist *)malloc(sizeof(STmplist));
if (curvelist == NULL) return 101;
if (strcmp(id, network->Curve[n].ID) == 0) return 0;
if (findcurve(network, id) > 0) return 0;
}
if (strlen(id) > MAXID) return 250;
// Initialize list element properties
else
{
curvelist->i = parser->MaxCurves;
strncpy(curvelist->ID, id, MAXID);
curvelist->x = NULL;
curvelist->y = NULL;
curvelist->next = parser->Curvelist;
parser->Curvelist = curvelist;
}
}
n = n + 2;
network->Curve = (Scurve *)realloc(network->Curve, n * sizeof(Scurve));
if (network->Curve == NULL) return 101;
(network->Ncurves)++;
// Initialize the curve
curve = &network->Curve[network->Ncurves];
strncpy(curve->ID, id, MAXID);
curve->Type = GENERIC_CURVE;
curve->Comment = NULL;
curve->Capacity = 0;
curve->Npts = 0;
curve->X = NULL;
curve->Y = NULL;
return 0;
}
STmplist *getlistitem(char *id, STmplist *list)
/*
**-------------------------------------------------------------
** Input: id = ID label
** list = pointer to head of a temporary list
** Output: returns list item with requested ID label
** Purpose: searches for item in temporary list
**-------------------------------------------------------------
*/
{
STmplist *item;
for (item = list; item != NULL; item = item->next)
{
if (strcmp(item->ID, id) == 0) return item;
}
return NULL;
}
int unlinked(Project *pr)
/*
**--------------------------------------------------------------
@@ -625,144 +621,6 @@ int unlinked(Project *pr)
return errcode;
}
int getpatterns(Project *pr)
/*
**-----------------------------------------------------------
** Input: none
** Output: returns error code
** Purpose: retrieves pattern data from temporary linked list
**-------------------------------------------------------------
*/
{
Network *net = &pr->network;
Hydraul *hyd = &pr->hydraul;
Parser *parser = &pr->parser;
int i, j;
SFloatlist *f;
STmplist *tmppattern;
Spattern *pattern;
// Start at head of the list of patterns
tmppattern = parser->Patlist;
// Traverse list of temporary patterns
while (tmppattern != NULL)
{
// Get index of temporary pattern in network's Pattern array
i = tmppattern->i;
// Check if this is the default pattern
if (strcmp(tmppattern->ID, parser->DefPatID) == 0) parser->DefPat = i;
// Copy temporary patttern to network's pattern
if (i >= 0 && i <= parser->MaxPats)
{
pattern = &net->Pattern[i];
strcpy(pattern->ID, tmppattern->ID);
/* Give pattern a length of at least 1 */
if (pattern->Length == 0) pattern->Length = 1;
// Allocate array of pattern factors
pattern->F = (double *)calloc(pattern->Length, sizeof(double));
if (pattern->F == NULL) return 101;
// Start at head of temporary pattern multiplier list
// (which holds multipliers in reverse order)
f = tmppattern->x;
j = pattern->Length - 1;
// Use at least one multiplier equal to 1.0
if (f == NULL) pattern->F[0] = 1.0;
// Traverse temporary multiplier list, copying Pattern array */
else while (f != NULL && j >= 0)
{
pattern->F[j] = f->value;
f = f->next;
j--;
}
}
tmppattern = tmppattern->next;
}
return 0;
}
int getcurves(Project *pr)
/*
**-----------------------------------------------------------
** Input: none
** Output: returns error code
** Purpose: retrieves curve data from temporary linked list
**-----------------------------------------------------------
*/
{
Network *net = &pr->network;
Parser *parser = &pr->parser;
int i, j;
double x;
char errmsg[MAXMSG+1];
SFloatlist *fx, *fy;
STmplist *tmpcurve;
Scurve *curve;
// Traverse list of temporary curves
tmpcurve = parser->Curvelist;
while (tmpcurve != NULL)
{
// Get index of temporary curve in network's Curve array
i = tmpcurve->i;
// Copy temporary curve to network's curve
if (i >= 1 && i <= parser->MaxCurves)
{
curve = &net->Curve[i];
strcpy(curve->ID, tmpcurve->ID);
// Check that network curve has data points
if (curve->Npts <= 0)
{
sprintf(pr->Msg, "Error 230: %s %s", geterrmsg(230, errmsg), curve->ID);
writeline(pr, pr->Msg);
return 200;
}
// Allocate memory for network's curve data
curve->X = (double *)calloc(curve->Npts, sizeof(double));
curve->Y = (double *)calloc(curve->Npts, sizeof(double));
if (curve->X == NULL || curve->Y == NULL) return 101;
// Traverse list of x,y data
x = BIG;
fx = tmpcurve->x;
fy = tmpcurve->y;
j = curve->Npts - 1;
while (fx != NULL && fy != NULL && j >= 0)
{
// Check that x data is in ascending order
if (fx->value >= x)
{
sprintf(pr->Msg, "Error 230: %s %s", geterrmsg(230, errmsg), curve->ID);
writeline(pr, pr->Msg);
return 200;
}
x = fx->value;
// Copy x,y data to network's curve
curve->X[j] = fx->value;
fx = fx->next;
curve->Y[j] = fy->value;
fy = fy->next;
j--;
}
}
tmpcurve = tmpcurve->next;
}
return 0;
}
int findmatch(char *line, char *keyword[])
/*
**--------------------------------------------------------------
@@ -828,8 +686,8 @@ int gettokens(char *s, char** Tok, int maxToks, char *comment)
**--------------------------------------------------------------
*/
{
int m, n;
size_t len;
int n;
size_t len, m;
char *c, *c2;
// clear comment

View File

@@ -7,7 +7,7 @@ Description: parses network data from a line of an EPANET input file
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 03/17/2019
Last Updated: 04/03/2019
******************************************************************************
*/
@@ -40,7 +40,6 @@ int powercurve(double, double, double, double, double, double *, double *,
// Imported Functions
extern int addnodeID(Network *, int, char *);
extern int addlinkID(Network *, int, char *);
extern STmplist *getlistitem(char *, STmplist *);
// Local functions
static int optionchoice(Project *, int);
@@ -87,7 +86,6 @@ int juncdata(Project *pr)
double el, // elevation
y = 0.0; // base demand
Pdemand demand; // demand record
STmplist *patlist; // list of demands
Snode *node;
// Add new junction to data base
@@ -104,9 +102,8 @@ int juncdata(Project *pr)
if (n >= 3 && !getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
if (n >= 4)
{
patlist = getlistitem(parser->Tok[3], parser->Patlist);
if (patlist == NULL) return setError(parser, 3, 205);
p = patlist->i;
p = findpattern(net, parser->Tok[3]);
if (p == 0) return setError(parser, 3, 205);
}
// Save junction data
@@ -162,7 +159,6 @@ int tankdata(Project *pr)
minvol = 0.0, // Minimum volume
diam = 0.0, // Diameter
area; // X-sect. area
STmplist *tmplist;
Snode *node;
Stank *tank;
@@ -186,9 +182,8 @@ int tankdata(Project *pr)
// Head pattern supplied
if (n == 3)
{
tmplist = getlistitem(parser->Tok[2], parser->Patlist);
if (tmplist == NULL) return setError(parser, 2, 205);
pattern = tmplist->i;
pattern = findpattern(net, parser->Tok[2]);
if (pattern == 0) return setError(parser, 2, 205);
}
}
else if (n < 6) return 201;
@@ -205,9 +200,8 @@ int tankdata(Project *pr)
// If volume curve supplied check it exists
if (n == 8)
{
tmplist = getlistitem(parser->Tok[7], parser->Curvelist);
if (tmplist == NULL) return setError(parser, 7, 206);
curve = tmplist->i;
curve = findcurve(net, parser->Tok[7]);
if (curve == 0) return setError(parser, 7, 206);
net->Curve[curve].Type = VOLUME_CURVE;
}
if (initlevel < 0.0) return setError(parser, 2, 209);
@@ -357,12 +351,12 @@ int pumpdata(Project *pr)
Network *net = &pr->network;
Parser *parser = &pr->parser;
int j,
int j, m, // Token array indexes
j1, // Start-node index
j2, // End-node index
m, n; // # data items
n, // # data items
c, p; // Curve & Pattern indexes
double y;
STmplist *tmplist; // Temporary list
Slink *link;
Spump *pump;
@@ -432,15 +426,15 @@ int pumpdata(Project *pr)
}
else if (match(parser->Tok[m - 1], w_HEAD)) // Custom pump curve
{
tmplist = getlistitem(parser->Tok[m], parser->Curvelist);
if (tmplist == NULL) return setError(parser, m, 206);
pump->Hcurve = tmplist->i;
c = findcurve(net, parser->Tok[m]);
if (c == 0) return setError(parser, m, 206);
pump->Hcurve = c;
}
else if (match(parser->Tok[m - 1], w_PATTERN)) // Speed/status pattern
{
tmplist = getlistitem(parser->Tok[m], parser->Patlist);
if (tmplist == NULL) return setError(parser, m, 205);
pump->Upat = tmplist->i;
p = findpattern(net, parser->Tok[m]);
if (p == 0) return setError(parser, m, 205);
pump->Upat = p;
}
else if (match(parser->Tok[m - 1], w_SPEED)) // Speed setting
{
@@ -469,7 +463,8 @@ int valvedata(Project *pr)
Network *net = &pr->network;
Parser *parser = &pr->parser;
int j1, // Start-node index
int c, // Curve index
j1, // Start-node index
j2, // End-node index
n; // # data items
char status = ACTIVE, // Valve status
@@ -477,7 +472,6 @@ int valvedata(Project *pr)
double diam = 0.0, // Valve diameter
setting, // Valve setting
lcoeff = 0.0; // Minor loss coeff.
STmplist *tmplist; // Temporary list
Slink *link;
// Add new valve to data base
@@ -508,10 +502,10 @@ int valvedata(Project *pr)
// Find headloss curve for GPV
if (type == GPV)
{
tmplist = getlistitem(parser->Tok[5], parser->Curvelist);
if (tmplist == NULL) return setError(parser, 5, 206);
setting = tmplist->i;
net->Curve[tmplist->i].Type = HLOSS_CURVE;
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);
@@ -558,43 +552,47 @@ int patterndata(Project *pr)
Network *net = &pr->network;
Parser *parser = &pr->parser;
int i, n;
int i, j, n, n1;
double x;
SFloatlist *f;
STmplist *p;
Spattern *pattern;
// "n" is the number of pattern factors contained in the line
n = parser->Ntokens - 1;
if (n < 1) return 201;
// Check for a new pattern
if (parser->PrevPat != NULL &&
strcmp(parser->Tok[0], parser->PrevPat->ID) == 0) p = parser->PrevPat;
// Check if previous input line was for the same pattern
if (parser->PrevPat && strcmp(parser->Tok[0], parser->PrevPat->ID) == 0)
{
pattern = parser->PrevPat;
}
// Otherwise retrieve pattern from the network's Pattern array
else
{
p = getlistitem(parser->Tok[0], parser->Patlist);
if (p == NULL) return setError(parser, 0, 205);
pattern = &(net->Pattern[p->i]);
i = findpattern(net, parser->Tok[0]);
if (i == 0) return setError(parser, 0, 205);
pattern = &(net->Pattern[i]);
if (pattern->Comment == NULL && parser->Comment[0])
{
pattern->Comment = xstrcpy(&pattern->Comment, parser->Comment, MAXMSG);
}
// Add parsed multipliers to the pattern
for (i = 1; i <= n; i++)
{
if (!getfloat(parser->Tok[i], &x)) return setError(parser, i, 202);
f = (SFloatlist *)malloc(sizeof(SFloatlist));
if (f == NULL) return 101;
f->value = x;
f->next = p->x;
p->x = f;
}
// Save # multipliers for pattern
net->Pattern[p->i].Length += n;
// Expand size of the pattern's factors array
n1 = pattern->Length;
pattern->Length += n;
pattern->F = realloc(pattern->F, pattern->Length * sizeof(double));
// Set previous pattern pointer
parser->PrevPat = p;
return (0);
// Add parsed multipliers to the pattern
for (j = 1; j <= n; j++)
{
if (!getfloat(parser->Tok[j], &x)) return setError(parser, j, 202);
pattern->F[n1 + j - 1] = x;
}
// Save a reference to this pattern for processing additional pattern data
parser->PrevPat = pattern;
return 0;
}
int curvedata(Project *pr)
@@ -612,46 +610,46 @@ int curvedata(Project *pr)
Network *net = &pr->network;
Parser *parser = &pr->parser;
int i;
double x, y;
SFloatlist *fx, *fy;
STmplist *c;
Scurve *curve;
// Check for valid curve ID
if (parser->Ntokens < 3) return 201;
if (parser->PrevCurve != NULL &&
strcmp(parser->Tok[0], parser->PrevCurve->ID) == 0) c = parser->PrevCurve;
else
{
c = getlistitem(parser->Tok[0], parser->Curvelist);
if (c == NULL) return setError(parser, 0, 206);
curve = &(net->Curve[c->i]);
curve->Comment = xstrcpy(&curve->Comment, parser->Comment, MAXMSG);
}
// Check for valid data
if (parser->Ntokens < 3) return 201;
if (!getfloat(parser->Tok[1], &x)) return setError(parser, 1, 202);
if (!getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
// Add new data point to curve
fx = (SFloatlist *)malloc(sizeof(SFloatlist));
if (fx == NULL) return 101;
fy = (SFloatlist *)malloc(sizeof(SFloatlist));
if (fy == NULL)
// Check if previous input line was for the same curve
if (parser->PrevCurve && strcmp(parser->Tok[0], parser->PrevCurve->ID) == 0)
{
free(fx);
return 101;
curve = parser->PrevCurve;
}
fx->value = x;
fx->next = c->x;
c->x = fx;
fy->value = y;
fy->next = c->y;
c->y = fy;
net->Curve[c->i].Npts++;
// Save the pointer to this curve
parser->PrevCurve = c;
// Otherwise retrieve curve from the network's Curve array
else
{
i = findcurve(net, parser->Tok[0]);
if (i == 0) return setError(parser, 0, 206);
curve = &(net->Curve[i]);
if (curve->Comment == NULL && parser->Comment[0])
{
curve->Comment = xstrcpy(&curve->Comment, parser->Comment, MAXMSG);
}
}
// Expand size of data arrays if need be
if (curve->Capacity == curve->Npts)
{
if (resizecurve(curve, curve->Capacity + 10) > 0) return 101;
}
// Add new data point to curve
curve->X[curve->Npts] = x;
curve->Y[curve->Npts] = y;
curve->Npts++;
// Save a reference to this curve for processing additional curve data
parser->PrevCurve = curve;
return 0;
}
@@ -713,7 +711,6 @@ int demanddata(Project *pr)
double y;
Pdemand demand;
Pdemand cur_demand;
STmplist *patlist;
// Extract data from tokens
n = parser->Ntokens;
@@ -733,9 +730,8 @@ int demanddata(Project *pr)
if (j > net->Njuncs) return 0;
if (n >= 3)
{
patlist = getlistitem(parser->Tok[2], parser->Patlist);
if (patlist == NULL) return setError(parser, 2, 205);
p = patlist->i;
p = findpattern(net, parser->Tok[2]);
if (p == 0) return setError(parser, 2, 205);
}
// Replace any demand entered in [JUNCTIONS] section
@@ -746,7 +742,10 @@ int demanddata(Project *pr)
// with what is specified in this section
demand->Base = y;
demand->Pat = p;
demand->Name = xstrcpy(&demand->Name, parser->Comment, MAXMSG);
if (parser->Comment[0])
{
demand->Name = xstrcpy(&demand->Name, parser->Comment, MAXID);
}
hyd->NodeDemand[j] = MISSING; // marker - next iteration will append a new category.
}
@@ -759,7 +758,11 @@ int demanddata(Project *pr)
if (demand == NULL) return 101;
demand->Base = y;
demand->Pat = p;
demand->Name = xstrcpy(&demand->Name, parser->Comment, MAXMSG);
demand->Name = NULL;
if (parser->Comment[0])
{
demand->Name = xstrcpy(&demand->Name, parser->Comment, MAXID);
}
demand->next = NULL;
cur_demand->next = demand;
}
@@ -900,7 +903,6 @@ int sourcedata(Project *pr)
p = 0; // Time pattern index
char type = CONCEN; // Source type
double c0 = 0; // Initial quality
STmplist *patlist;
Psource source;
// Check for enough tokens & that source node exists
@@ -929,9 +931,8 @@ int sourcedata(Project *pr)
if (n > i + 1 && strlen(parser->Tok[i + 1]) > 0 &&
strcmp(parser->Tok[i + 1], "*") != 0)
{
patlist = getlistitem(parser->Tok[i + 1], parser->Patlist);
if (patlist == NULL) return setError(parser, i+1, 205);
p = patlist->i;
p = findpattern(net, parser->Tok[i + 1]);
if (p == 0) return setError(parser, i + 1, 205);
}
// Destroy any existing source assigned to node
@@ -1335,10 +1336,9 @@ int energydata(Project *pr)
Hydraul *hyd = &pr->hydraul;
Parser *parser = &pr->parser;
int j, k, n;
int j, k, n, p, c;
double y;
STmplist *listitem;
Slink *Link = net->Link;
Spump *Pump = net->Pump;
@@ -1385,10 +1385,10 @@ int energydata(Project *pr)
// Price PATTERN being set
else if (match(parser->Tok[n - 2], w_PATTERN))
{
listitem = getlistitem(parser->Tok[n - 1], parser->Patlist);
if (listitem == NULL) return setError(parser, n - 1, 205);
if (j == 0) hyd->Epat = listitem->i;
else Pump[j].Epat = listitem->i;
p = findpattern(net, parser->Tok[n - 1]);
if (p == 0) return setError(parser, n - 1, 205);
if (j == 0) hyd->Epat = p;
else Pump[j].Epat = p;
return 0;
}
@@ -1403,10 +1403,10 @@ int energydata(Project *pr)
}
else
{
listitem = getlistitem(parser->Tok[n - 1], parser->Curvelist);
if (listitem == NULL) return setError(parser, n - 1, 206);
Pump[j].Ecurve = listitem->i;
net->Curve[listitem->i].Type = EFFIC_CURVE;
c = findcurve(net, parser->Tok[n - 1]);
if (c == 0) return setError(parser, n - 1, 206);
Pump[j].Ecurve = c;
net->Curve[c].Type = EFFIC_CURVE;
}
return 0;
}

View File

@@ -7,7 +7,7 @@
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 03/17/2019
Last Updated: 04/03/2019
******************************************************************************
*/
@@ -274,9 +274,6 @@ void initpointers(Project *pr)
pr->network.NodeHashTable = NULL;
pr->network.LinkHashTable = NULL;
pr->parser.Patlist = NULL;
pr->parser.Curvelist = NULL;
pr->hydraul.smatrix.Aii = NULL;
pr->hydraul.smatrix.Aij = NULL;
pr->hydraul.smatrix.F = NULL;
@@ -341,8 +338,8 @@ int allocdata(Project *pr)
ERRCODE(MEMCHECK(pr->hydraul.LinkStatus));
}
// Allocate memory for tanks, sources, pumps, valves,
// controls, demands, time patterns, & operating curves
// Allocate memory for tanks, sources, pumps, valves, and controls
// (memory for Patterns and Curves arrays expanded as each is added)
if (!errcode)
{
pr->network.Tank =
@@ -353,35 +350,15 @@ int allocdata(Project *pr)
(Svalve *)calloc(pr->parser.MaxValves + 1, sizeof(Svalve));
pr->network.Control =
(Scontrol *)calloc(pr->parser.MaxControls + 1, sizeof(Scontrol));
pr->network.Pattern =
(Spattern *)calloc(pr->parser.MaxPats + 1, sizeof(Spattern));
pr->network.Curve =
(Scurve *)calloc(pr->parser.MaxCurves + 1, sizeof(Scurve));
ERRCODE(MEMCHECK(pr->network.Tank));
ERRCODE(MEMCHECK(pr->network.Pump));
ERRCODE(MEMCHECK(pr->network.Valve));
ERRCODE(MEMCHECK(pr->network.Control));
ERRCODE(MEMCHECK(pr->network.Pattern));
ERRCODE(MEMCHECK(pr->network.Curve));
}
// Initialize pointers used in patterns, curves, and demand category lists
// Initialize pointers used in nodes and links
if (!errcode)
{
for (n = 0; n <= pr->parser.MaxPats; n++)
{
pr->network.Pattern[n].Length = 0;
pr->network.Pattern[n].F = NULL;
pr->network.Pattern[n].Comment = NULL;
}
for (n = 0; n <= pr->parser.MaxCurves; n++)
{
pr->network.Curve[n].Npts = 0;
pr->network.Curve[n].Type = GENERIC_CURVE;
pr->network.Curve[n].X = NULL;
pr->network.Curve[n].Y = NULL;
pr->network.Curve[n].Comment = NULL;
}
for (n = 0; n <= pr->parser.MaxNodes; n++)
{
pr->network.Node[n].D = NULL; // node demand
@@ -399,43 +376,6 @@ int allocdata(Project *pr)
return errcode;
}
void freeTmplist(STmplist *t)
/*----------------------------------------------------------------
** Input: t = pointer to start of a temporary list
** Output: none
** Purpose: frees memory used for temporary storage
** of pattern & curve data
**----------------------------------------------------------------
*/
{
STmplist *tnext;
while (t != NULL)
{
tnext = t->next;
freeFloatlist(t->x);
freeFloatlist(t->y);
free(t);
t = tnext;
}
}
void freeFloatlist(SFloatlist *f)
/*----------------------------------------------------------------
** Input: f = pointer to start of list of floats
** Output: none
** Purpose: frees memory used for storing list of floats
**----------------------------------------------------------------
*/
{
SFloatlist *fnext;
while (f != NULL)
{
fnext = f->next;
free(f);
f = fnext;
}
}
void freedata(Project *pr)
/*----------------------------------------------------------------
** Input: none
@@ -446,7 +386,6 @@ void freedata(Project *pr)
{
int j;
Pdemand demand, nextdemand;
Psource source;
// Free memory for computed results
free(pr->hydraul.NodeDemand);
@@ -474,8 +413,7 @@ void freedata(Project *pr)
demand = nextdemand;
}
// Free memory used for WQ source data
source = pr->network.Node[j].S;
free(source);
free(pr->network.Node[j].S);
free(pr->network.Node[j].Comment);
}
free(pr->network.Node);
@@ -511,7 +449,8 @@ void freedata(Project *pr)
// Free memory for curves
if (pr->network.Curve != NULL)
{
for (j = 0; j <= pr->parser.MaxCurves; j++)
// There is no Curve[0]
for (j = 1; j <= pr->parser.MaxCurves; j++)
{
free(pr->network.Curve[j].X);
free(pr->network.Curve[j].Y);
@@ -809,6 +748,40 @@ int findvalve(Network *network, int index)
return NOTFOUND;
}
int findpattern(Network *network, char *id)
/*----------------------------------------------------------------
** Input: id = time pattern ID
** Output: none
** Returns: time pattern index, or 0 if pattern not found
** Purpose: finds index of time pattern given its ID
**----------------------------------------------------------------
*/
{
int i;
for (i = 1; i <= network->Npats; i++)
{
if (strcmp(id, network->Pattern[i].ID) == 0) return i;
}
return 0;
}
int findcurve(Network *network, char *id)
/*----------------------------------------------------------------
** Input: id = data curve ID
** Output: none
** Returns: data curve index, or 0 if curve not found
** Purpose: finds index of data curve given its ID
**----------------------------------------------------------------
*/
{
int i;
for (i = 1; i <= network->Ncurves; i++)
{
if (strcmp(id, network->Curve[i].ID) == 0) return i;
}
return 0;
}
void adjustpattern(int *pat, int index)
/*----------------------------------------------------------------
** Local function that modifies a reference to a deleted time pattern
@@ -904,6 +877,35 @@ void adjustcurves(Network *network, int index)
}
}
int resizecurve(Scurve *curve, int size)
/*----------------------------------------------------------------
** Input: curve = a data curve object
** size = desired number of curve data points
** Output: error code
** Purpose: resizes a data curve to a desired size
**----------------------------------------------------------------
*/
{
double *x;
double *y;
if (curve->Capacity < size)
{
x = (double *)realloc(curve->X, size * sizeof(double));
if (x == NULL) return 101;
y = (double *)realloc(curve->Y, size * sizeof(double));
if (y == NULL)
{
free(x);
return 101;
}
curve->X = x;
curve->Y = y;
curve->Capacity = size;
}
return 0;
}
int getcomment(Network *network, int object, int index, char *comment)
//----------------------------------------------------------------
// Input: object = a type of network object

View File

@@ -317,23 +317,6 @@ struct IDstring // Holds component ID label
char ID[MAXID+1];
};
struct Floatlist // Element of List of Numbers
{
double value; // element's numerical value
struct Floatlist *next; // next element on the list
};
typedef struct Floatlist SFloatlist;
struct Tmplist // Item of Temporary List of Objects
{
int i; // object's index
char ID[MAXID+1]; // object's ID name
SFloatlist *x; // list of data values
SFloatlist *y; // list of data values
struct Tmplist *next; // next object on list
};
typedef struct Tmplist STmplist; // Pointer to temporary list of objects
typedef struct // Time Pattern Object
{
char ID[MAXID+1]; // pattern ID
@@ -348,6 +331,7 @@ typedef struct // Curve Object
char *Comment; // curve comment
CurveType Type; // curve type
int Npts; // number of points
int Capacity; // size of X & Y arrays
double *X; // x-values
double *Y; // y-values
} Scurve;
@@ -576,12 +560,8 @@ typedef struct {
Pressflag, // Pressure units flag
DefPat; // Default demand pattern
STmplist
*Patlist, // Temporary time pattern list
*PrevPat, // Previous pattern list element
*Curvelist, // Temporary list of curves
*PrevCurve; // Previous curve list element
Spattern *PrevPat; // Previous pattern processed
Scurve *PrevCurve; // Previous curve processed
double *X; // Temporary array for curve data
} Parser;