Merging latest from dev, trying to get import lib generated

This commit is contained in:
Michael Tryby
2018-07-03 17:38:40 -04:00
73 changed files with 3622 additions and 16583 deletions

View File

@@ -71,11 +71,12 @@ This module calls the following functions that reside in other modules:
runhyd()
nexthyd()
closehyd()
resistance()
tankvolume()
getenergy()
setlinkstatus()
setlinksetting()
HYDCOEFFS
resistcoeff()
QUALITY.C
openqual()
initqual()
@@ -108,6 +109,10 @@ execute function x and set the error code equal to its return value.
#ifdef __WIN32__
#define WINDOWS
#endif
#ifdef WINDOWS
#include <windows.h>
#endif
/************************************************************/
#include <stdio.h>
@@ -125,7 +130,7 @@ execute function x and set the error code equal to its return value.
#include "text.h"
#include "types.h"
#define EXTERN
#include "epanet2.h"
////////////////////////////////////////////#include "epanet2.h"
#include "vars.h"
/****************************************************************
@@ -186,208 +191,282 @@ int DLLEXPORT ENsaveinpfile(char *filename) {
}
int DLLEXPORT ENclose() { return EN_close(_defaultModel); }
int DLLEXPORT ENsolveH() { return EN_solveH(_defaultModel); }
int DLLEXPORT ENsaveH() { return EN_saveH(_defaultModel); }
int DLLEXPORT ENopenH() { return EN_openH(_defaultModel); }
int DLLEXPORT ENinitH(int flag) { return EN_initH(_defaultModel, flag); }
int DLLEXPORT ENrunH(long *t) { return EN_runH(_defaultModel, t); }
int DLLEXPORT ENnextH(long *tstep) { return EN_nextH(_defaultModel, tstep); }
int DLLEXPORT ENcloseH() { return EN_closeH(_defaultModel); }
int DLLEXPORT ENsavehydfile(char *filename) {
return EN_savehydfile(_defaultModel, filename);
}
int DLLEXPORT ENusehydfile(char *filename) {
return EN_usehydfile(_defaultModel, filename);
}
int DLLEXPORT ENsolveQ() { return EN_solveQ(_defaultModel); }
int DLLEXPORT ENopenQ() { return EN_openQ(_defaultModel); }
int DLLEXPORT ENinitQ(int saveflag) {
return EN_initQ(_defaultModel, saveflag);
}
int DLLEXPORT ENrunQ(long *t) { return EN_runQ(_defaultModel, t); }
int DLLEXPORT ENnextQ(long *tstep) { return EN_nextQ(_defaultModel, tstep); }
int DLLEXPORT ENstepQ(long *tleft) { return EN_stepQ(_defaultModel, tleft); }
int DLLEXPORT ENcloseQ() { return EN_closeQ(_defaultModel); }
int DLLEXPORT ENwriteline(char *line) {
return EN_writeline(_defaultModel, line);
}
int DLLEXPORT ENreport() { return EN_report(_defaultModel); }
int DLLEXPORT ENresetreport() { return EN_resetreport(_defaultModel); }
int DLLEXPORT ENsetreport(char *s) { return EN_setreport(_defaultModel, s); }
int DLLEXPORT ENgetversion(int *v) { return EN_getversion(v); }
int DLLEXPORT ENgetcontrol(int cindex, int *ctype, int *lindex,
EN_API_FLOAT_TYPE *setting, int *nindex,
EN_API_FLOAT_TYPE *level) {
return EN_getcontrol(_defaultModel, cindex, ctype, lindex, setting, nindex,
level);
}
int DLLEXPORT ENgetcount(int code, int *count) {
return EN_getcount(_defaultModel, (EN_CountType)code, count);
}
int DLLEXPORT ENgetoption(int code, EN_API_FLOAT_TYPE *value) {
return EN_getoption(_defaultModel, (EN_Option)code, value);
}
int DLLEXPORT ENgettimeparam(int code, long *value) {
return EN_gettimeparam(_defaultModel, code, value);
}
int DLLEXPORT ENgetflowunits(int *code) {
return EN_getflowunits(_defaultModel, code);
}
int DLLEXPORT ENsetflowunits(int code) {
return EN_setflowunits(_defaultModel, code);
}
int DLLEXPORT ENgetpatternindex(char *id, int *index) {
return EN_getpatternindex(_defaultModel, id, index);
}
int DLLEXPORT ENgetpatternid(int index, char *id) {
return EN_getpatternid(_defaultModel, index, id);
}
int DLLEXPORT ENgetpatternlen(int index, int *len) {
return EN_getpatternlen(_defaultModel, index, len);
}
int DLLEXPORT ENgetpatternvalue(int index, int period,
EN_API_FLOAT_TYPE *value) {
return EN_getpatternvalue(_defaultModel, index, period, value);
}
int DLLEXPORT ENgetcurveindex(char *id, int *index) {
return EN_getcurveindex(_defaultModel, id, index);
}
int DLLEXPORT ENgetcurveid(int index, char *id) {
return EN_getcurveid(_defaultModel, index, id);
}
int DLLEXPORT ENgetcurvelen(int index, int *len) {
return EN_getcurvelen(_defaultModel, index, len);
}
int DLLEXPORT ENgetcurvevalue(int index, int pnt, EN_API_FLOAT_TYPE *x,
EN_API_FLOAT_TYPE *y) {
return EN_getcurvevalue(_defaultModel, index, pnt, x, y);
}
int DLLEXPORT ENgetqualtype(int *qualcode, int *tracenode) {
return EN_getqualtype(_defaultModel, qualcode, tracenode);
}
int DLLEXPORT ENgetqualinfo(int *qualcode, char *chemname, char *chemunits,
int *tracenode) {
return EN_getqualinfo(_defaultModel, qualcode, chemname, chemunits,
tracenode);
}
int DLLEXPORT ENgeterror(int errcode, char *errmsg, int n) {
return EN_geterror(errcode, errmsg, n);
}
int DLLEXPORT ENgetstatistic(int code, EN_API_FLOAT_TYPE *value) {
return EN_getstatistic(_defaultModel, code, value);
}
int DLLEXPORT ENgetnodeindex(char *id, int *index) {
return EN_getnodeindex(_defaultModel, id, index);
}
int DLLEXPORT ENgetnodeid(int index, char *id) {
return EN_getnodeid(_defaultModel, index, id);
}
int DLLEXPORT ENgetnodetype(int index, int *code) {
return EN_getnodetype(_defaultModel, index, code);
}
int DLLEXPORT ENgetcoord(int index, EN_API_FLOAT_TYPE *x,
EN_API_FLOAT_TYPE *y) {
return EN_getcoord(_defaultModel, index, x, y);
}
int DLLEXPORT ENsetcoord(int index, EN_API_FLOAT_TYPE x, EN_API_FLOAT_TYPE y) {
return EN_setcoord(_defaultModel, index, x, y);
}
int DLLEXPORT ENgetnodevalue(int index, int code, EN_API_FLOAT_TYPE *value) {
return EN_getnodevalue(_defaultModel, index, code, value);
}
int DLLEXPORT ENgetlinkindex(char *id, int *index) {
return EN_getlinkindex(_defaultModel, id, index);
}
int DLLEXPORT ENgetlinkid(int index, char *id) {
return EN_getlinkid(_defaultModel, index, id);
}
int DLLEXPORT ENgetlinktype(int index, EN_LinkType *code) {
return EN_getlinktype(_defaultModel, index, code);
}
int DLLEXPORT ENgetlinknodes(int index, int *node1, int *node2) {
return EN_getlinknodes(_defaultModel, index, node1, node2);
}
int DLLEXPORT ENgetlinkvalue(int index, int code, EN_API_FLOAT_TYPE *value) {
return EN_getlinkvalue(_defaultModel, index, (EN_LinkProperty)code, value);
}
int DLLEXPORT ENgetcurve(int curveIndex, char *id, int *nValues,
EN_API_FLOAT_TYPE **xValues,
EN_API_FLOAT_TYPE **yValues) {
return EN_getcurve(_defaultModel, curveIndex, id, nValues, xValues, yValues);
}
int DLLEXPORT ENsetcontrol(int cindex, int ctype, int lindex,
EN_API_FLOAT_TYPE setting, int nindex,
EN_API_FLOAT_TYPE level) {
return EN_setcontrol(_defaultModel, cindex, ctype, lindex, setting, nindex,
level);
}
int DLLEXPORT ENsetnodevalue(int index, int code, EN_API_FLOAT_TYPE v) {
return EN_setnodevalue(_defaultModel, index, code, v);
}
int DLLEXPORT ENsetlinkvalue(int index, int code, EN_API_FLOAT_TYPE v) {
return EN_setlinkvalue(_defaultModel, index, code, v);
}
int DLLEXPORT ENaddpattern(char *id) {
return EN_addpattern(_defaultModel, id);
}
int DLLEXPORT ENsetpattern(int index, EN_API_FLOAT_TYPE *f, int n) {
return EN_setpattern(_defaultModel, index, f, n);
}
int DLLEXPORT ENsetpatternvalue(int index, int period,
EN_API_FLOAT_TYPE value) {
return EN_setpatternvalue(_defaultModel, index, period, value);
}
int DLLEXPORT ENaddcurve(char *id) { return EN_addcurve(_defaultModel, id); }
int DLLEXPORT ENsetcurve(int index, EN_API_FLOAT_TYPE *x, EN_API_FLOAT_TYPE *y,
int n) {
return EN_setcurve(_defaultModel, index, x, y, n);
}
int DLLEXPORT ENsetcurvevalue(int index, int pnt, EN_API_FLOAT_TYPE x,
EN_API_FLOAT_TYPE y) {
return EN_setcurvevalue(_defaultModel, index, pnt, x, y);
}
int DLLEXPORT ENsettimeparam(int code, long value) {
return EN_settimeparam(_defaultModel, code, value);
}
int DLLEXPORT ENsetoption(int code, EN_API_FLOAT_TYPE v) {
return EN_setoption(_defaultModel, code, v);
}
int DLLEXPORT ENsetstatusreport(int code) {
return EN_setstatusreport(_defaultModel, code);
}
int DLLEXPORT ENsetqualtype(int qualcode, char *chemname, char *chemunits,
char *tracenode) {
return EN_setqualtype(_defaultModel, qualcode, chemname, chemunits,
tracenode);
}
int DLLEXPORT ENgetheadcurveindex(int index, int *curveindex) {
return EN_getheadcurveindex(_defaultModel, index, curveindex);
}
int DLLEXPORT ENsetheadcurveindex(int index, int curveindex) {
return EN_setheadcurveindex(_defaultModel, index, curveindex);
}
int DLLEXPORT ENgetpumptype(int index, int *type) {
return EN_getpumptype(_defaultModel, index, type);
}
int DLLEXPORT ENgetnumdemands(int nodeIndex, int *numDemands) {
return EN_getnumdemands(_defaultModel, nodeIndex, numDemands);
}
int DLLEXPORT ENgetbasedemand(int nodeIndex, int demandIdx,
EN_API_FLOAT_TYPE *baseDemand) {
return EN_getbasedemand(_defaultModel, nodeIndex, demandIdx, baseDemand);
}
int DLLEXPORT ENsetbasedemand(int nodeIndex, int demandIdx,
EN_API_FLOAT_TYPE baseDemand) {
return EN_setbasedemand(_defaultModel, nodeIndex, demandIdx, baseDemand);
}
int DLLEXPORT ENgetdemandpattern(int nodeIndex, int demandIdx, int *pattIdx) {
return EN_getdemandpattern(_defaultModel, nodeIndex, demandIdx, pattIdx);
}
int DLLEXPORT ENgetaveragepatternvalue(int index, EN_API_FLOAT_TYPE *value) {
return EN_getaveragepatternvalue(_defaultModel, index, value);
}
int DLLEXPORT ENgetrule(int index, int *nPremises, int *nTrueActions, int *nFalseActions, EN_API_FLOAT_TYPE *priority) {
int DLLEXPORT ENgetrule(int index, int *nPremises, int *nTrueActions,
int *nFalseActions, EN_API_FLOAT_TYPE *priority) {
return EN_getrule(_defaultModel, index, nPremises, nTrueActions, nFalseActions, priority);
}
@@ -415,19 +494,23 @@ int DLLEXPORT ENsetpremisevalue(int indexRule, int indexPremise, EN_API_FLOAT_TY
return EN_setpremisevalue(_defaultModel, indexRule, indexPremise, value);
}
int DLLEXPORT ENgettrueaction(int indexRule, int indexAction, int *indexLink, int *status, EN_API_FLOAT_TYPE *setting){
int DLLEXPORT ENgettrueaction(int indexRule, int indexAction, int *indexLink,
int *status, EN_API_FLOAT_TYPE *setting){
return EN_gettrueaction(_defaultModel, indexRule, indexAction, indexLink, status, setting);
}
int DLLEXPORT ENsettrueaction(int indexRule, int indexAction, int indexLink, int status, EN_API_FLOAT_TYPE setting){
int DLLEXPORT ENsettrueaction(int indexRule, int indexAction, int indexLink,
int status, EN_API_FLOAT_TYPE setting){
return EN_settrueaction(_defaultModel, indexRule, indexAction, indexLink, status, setting);
}
int DLLEXPORT ENgetfalseaction(int indexRule, int indexAction, int *indexLink, int *status, EN_API_FLOAT_TYPE *setting){
int DLLEXPORT ENgetfalseaction(int indexRule, int indexAction, int *indexLink,
int *status, EN_API_FLOAT_TYPE *setting){
return EN_getfalseaction(_defaultModel, indexRule, indexAction, indexLink, status, setting);
}
int DLLEXPORT ENsetfalseaction(int indexRule, int indexAction, int indexLink, int status, EN_API_FLOAT_TYPE setting){
int DLLEXPORT ENsetfalseaction(int indexRule, int indexAction, int indexLink,
int status, EN_API_FLOAT_TYPE setting){
return EN_setfalseaction(_defaultModel, indexRule, indexAction, indexLink, status, setting);
}
@@ -438,16 +521,20 @@ int DLLEXPORT ENgetruleID(int indexRule, char* id){
int DLLEXPORT ENsetlinktype(char *id, EN_LinkType toType) {
return EN_setlinktype(_defaultModel, id, toType);
}
int DLLEXPORT ENaddnode(char *id, EN_NodeType nodeType) {
return EN_addnode(_defaultModel, id, nodeType);
}
int DLLEXPORT ENaddlink(char *id, EN_LinkType linkType, char *fromNode,
char *toNode) {
return EN_addlink(_defaultModel, id, linkType, fromNode, toNode);
}
int DLLEXPORT ENdeletelink(int index) {
return EN_deletelink(_defaultModel, index);
}
int DLLEXPORT ENdeletenode(int index) {
return EN_deletenode(_defaultModel, index);
}
@@ -734,7 +821,6 @@ int DLLEXPORT EN_solveH(EN_ProjectHandle ph)
tstep = 0;
ERRCODE(EN_runH(ph, &t));
ERRCODE(EN_nextH(ph, &tstep));
/*** Updated 6/24/02 ***/
writecon("\b\b\b\b\b\b\b\b\b\b");
} while (tstep > 0);
@@ -858,8 +944,10 @@ int DLLEXPORT EN_initH(EN_ProjectHandle ph, int flag)
errcode = openhydfile(p);
if (!errcode)
p->save_options.Saveflag = TRUE;
else
else {
errmsg(p, errcode);
return errcode;
}
}
/* Initialize hydraulics */
@@ -1333,6 +1421,14 @@ int DLLEXPORT EN_getoption(EN_ProjectHandle ph, EN_Option code,
case EN_DEMANDMULT:
v = hyd->Dmult;
break;
case EN_HEADERROR:
v = hyd->HeadErrorLimit * Ucf[HEAD];
break;
case EN_FLOWCHANGE:
v = hyd->FlowChangeLimit * Ucf[FLOW];
break;
default:
return (251);
}
@@ -1627,11 +1723,12 @@ int DLLEXPORT EN_getqualtype(EN_ProjectHandle ph, int *qualcode, int *tracenode)
return (0);
}
int DLLEXPORT EN_getqualinfo(EN_ProjectHandle ph, int *qualcode, char *chemname,
char *chemunits, int *tracenode) {
EN_Project *p = (EN_Project*)ph;
ENgetqualtype(qualcode, tracenode);
int DLLEXPORT EN_getqualinfo(EN_Project *p, int *qualcode, char *chemname,
char *chemunits, int *tracenode) {
EN_getqualtype(p, qualcode, tracenode);
if (p->quality.Qualflag == TRACE) {
strncpy(chemname, "", MAXID);
strncpy(chemunits, "dimensionless", MAXID);
@@ -1665,7 +1762,7 @@ int DLLEXPORT EN_geterror(int errcode, char *errmsg, int n) {
strncpy(errmsg, WARN6, n);
break;
default:
geterrmsg(n, newMsg);
geterrmsg(errcode, newMsg);
strncpy(errmsg, newMsg, n);
}
if (strlen(errmsg) == 0)
@@ -2720,7 +2817,7 @@ int DLLEXPORT EN_setlinkvalue(EN_ProjectHandle ph, int index, int code,
r = Link[index].Diam / value; /* Ratio of old to new diam */
Link[index].Km *= SQR(r) * SQR(r); /* Adjust minor loss factor */
Link[index].Diam = value; /* Update diameter */
resistance(p, index); /* Update resistance factor */
resistcoeff(p, index); /* Update resistance coeff. */
}
break;
@@ -2729,7 +2826,7 @@ int DLLEXPORT EN_setlinkvalue(EN_ProjectHandle ph, int index, int code,
if (value <= 0.0)
return (202);
Link[index].Len = value / Ucf[ELEV];
resistance(p, index);
resistcoeff(p, index);
}
break;
@@ -2740,7 +2837,7 @@ int DLLEXPORT EN_setlinkvalue(EN_ProjectHandle ph, int index, int code,
Link[index].Kc = value;
if (hyd->Formflag == DW)
Link[index].Kc /= (1000.0 * Ucf[ELEV]);
resistance(p, index);
resistcoeff(p, index);
}
break;
@@ -3259,6 +3356,18 @@ int DLLEXPORT EN_setoption(EN_ProjectHandle ph, int code, EN_API_FLOAT_TYPE v)
return (202);
hyd->Dmult = value;
break;
case EN_HEADERROR:
if (value < 0.0)
return (202);
hyd->HeadErrorLimit = value / Ucf[HEAD];
break;
case EN_FLOWCHANGE:
if (value < 0.0)
return (202);
hyd->FlowChangeLimit = value / Ucf[FLOW];
break;
default:
return (251);
}
@@ -3518,7 +3627,7 @@ int openhydfile(EN_Project *p)
out->HydFile = NULL;
switch (out->Hydflag) {
case SCRATCH:
getTmpName(p, out->HydFname);
getTmpName(p, out->HydFname);
out->HydFile = fopen(out->HydFname, "w+b");
break;
case SAVE:
@@ -3936,7 +4045,6 @@ void freedata(EN_Project *p)
----------------------------------------------------------------
*/
/*** New function for 2.00.12 ***/
char *getTmpName(EN_Project *p, char *fname)
//
// Input: fname = file name string
@@ -3944,7 +4052,25 @@ char *getTmpName(EN_Project *p, char *fname)
// Purpose: creates a temporary file name with path prepended to it.
//
{
out_file_t *out = &p->out_files;
#ifdef _WIN32
char* name = NULL;
// --- use Windows _tempnam function to get a pointer to an
// unused file name that begins with "en"
name = _tempnam(NULL, "en");
if (name == NULL) return NULL;
// --- copy the file name to fname
if (strlen(name) < MAXFNAME) strncpy(fname, name, MAXFNAME);
else fname = NULL;
// --- free the pointer returned by _tempnam
if (name) free(name);
/*
/////////////////// DEPRECATED /////////////////////////////////////
// --- for Windows systems:
#ifdef WINDOWS
// --- use system function tmpnam() to create a temporary file name
@@ -3970,6 +4096,7 @@ char *getTmpName(EN_Project *p, char *fname)
// --- now add the prefix to the file name
strcat(fname, name);
*/
// --- for non-Windows systems:
#else
@@ -4362,16 +4489,15 @@ int DLLEXPORT EN_addnode(EN_ProjectHandle ph, char *id, EN_NodeType nodeType) {
qu->NodeQual = (double *)realloc(qu->NodeQual, (net->Nnodes + 2) * sizeof(double));
hyd->NodeHead = (double *)realloc(hyd->NodeHead, (net->Nnodes + 2) * sizeof(double));
nIdx = net->Nnodes + 1;
node = &net->Node[nIdx];
coord = &net->Coord[nIdx];
if (nodeType == EN_JUNCTION) {
net->Njuncs++;
nIdx = net->Njuncs;
node = &net->Node[nIdx];
coord = &net->Coord[nIdx];
demand = (struct Sdemand *)malloc(sizeof(struct Sdemand));
demand->Base = 0.0;
demand->Pat = 0;
demand->Pat = hyd->DefPat; // Use default pattern
demand->next = NULL;
node->D = demand;
@@ -4396,6 +4522,9 @@ int DLLEXPORT EN_addnode(EN_ProjectHandle ph, char *id, EN_NodeType nodeType) {
}
}
} else {
nIdx = net->Nnodes++;
node = &net->Node[nIdx];
coord = &net->Coord[nIdx];
net->Ntanks++;
/* resize tanks array */
@@ -4436,8 +4565,7 @@ int DLLEXPORT EN_addnode(EN_ProjectHandle ph, char *id, EN_NodeType nodeType) {
node->C0 = 0;
node->Ke = 0;
node->Rpt = 0;
coord->HaveCoords = FALSE;
coord->X = 0;
coord->Y = 0;

View File

@@ -31,32 +31,34 @@ AUTHOR: L. Rossman
#include "types.h"
void initpointers(EN_Project *p); /* Initializes pointers */
int allocdata(EN_Project *p); /* Allocates memory */
void freeTmplist(STmplist *); /* Frees items in linked list */
void freeFloatlist(SFloatlist *); /* Frees list of floats */
void freedata(EN_Project *p); /* Frees allocated memory */
int openfiles(EN_Project *p, const char *, const char *, const char *); /* Opens input & report files */
int openhydfile(EN_Project *p); /* Opens hydraulics file */
int openoutfile(EN_Project *p); /* Opens binary output file */
int strcomp(const char *, const char *); /* Compares two strings */
char* getTmpName(EN_Project *p, char* fname); /* Gets temporary file name */
double interp(int, double *,double *, double); /* Interpolates a data curve */
void initpointers(EN_Project *pr); /* Initializes pointers */
int allocdata(EN_Project *pr); /* Allocates memory */
void freeTmplist(STmplist *); /* Frees items in linked list */
void freeFloatlist(SFloatlist *); /* Frees list of floats */
void freedata(EN_Project *pr); /* Frees allocated memory */
int openfiles(EN_Project *pr, const char *,
const char *,const char *); /* Opens input & report files */
int openhydfile(EN_Project *pr); /* Opens hydraulics file */
int openoutfile(EN_Project *pr); /* Opens binary output file */
int strcomp(const char *, const char *); /* Compares two strings */
char* getTmpName(EN_Project *p, char* fname); /* Gets temporary file name */
double interp(int n, double x[], double y[],
double xx); /* Interpolates a data curve */
int findnode(EN_Network *n, char *); /* Finds node's index from ID */
int findlink(EN_Network *n, char *); /* Finds link's index from ID */
int findtank(EN_Network *n, int); /* Find tank index from node index */ // (AH)
int findvalve(EN_Network *n, int); /* Find valve index from node index */ // (AH)
int findpump(EN_Network *n, int); /* Find pump index from node index */ // (AH)
char *geterrmsg(int errcode, char *msg); /* Gets text of error message */
void errmsg(EN_Project *p, int); /* Reports program error */
void writecon(const char *); /* Writes text to console */
void writewin(void (*vp)(char *), char *); /* Passes text to calling app */
int findnode(EN_Network *n, char *); /* Finds node's index from ID */
int findlink(EN_Network *n, char *); /* Finds link's index from ID */
int findtank(EN_Network *n, int); /* Find tank index from node index */ // (AH)
int findvalve(EN_Network *n, int); /* Find valve index from node index */ // (AH)
int findpump(EN_Network *n, int); /* Find pump index from node index */ // (AH)
char *geterrmsg(int errcode, char *msg); /* Gets text of error message */
void errmsg(EN_Project *p, int); /* Reports program error */
void writecon(const char *); /* Writes text to console */
void writewin(void (*vp)(char *), char *); /* Passes text to calling app */
/* ------- INPUT1.C --------------------*/
int getdata(EN_Project *pr); /* Gets network data */
void setdefaults(EN_Project *pr); /* Sets default values */
void initreport(report_options_t *r); /* Initializes report options */
void initreport(report_options_t *r); /* Initializes report options */
void adjustdata(EN_Project *pr); /* Adjusts input data */
int inittanks(EN_Project *pr); /* Initializes tank levels */
void initunits(EN_Project *pr); /* Determines reporting units */
@@ -65,23 +67,24 @@ void convertunits(EN_Project *pr); /* Converts data to std. uni
/* -------- INPUT2.C -------------------*/
int netsize(EN_Project *pr); /* Determines network size */
int readdata(EN_Project *pr); /* Reads in network data */
int newline(EN_Project *pr, int, char *); /* Processes new line of data */
int addnodeID(EN_Network *n, int, char *); /* Adds node ID to data base */
int addlinkID(EN_Network *n, int, char *); /* Adds link ID to data base */
int addpattern(parser_data_t *par, char *); /* Adds pattern to data base */
int addcurve(parser_data_t *par, char *); /* Adds curve to data base */
STmplist *findID(char *, STmplist *); /* Locates ID on linked list */
int newline(EN_Project *pr, int, char *); /* Processes new line of data */
int addnodeID(EN_Network *n, int, char *); /* Adds node ID to data base */
int addlinkID(EN_Network *n, int, char *); /* Adds link ID to data base */
int addpattern(parser_data_t *par, char *); /* Adds pattern to data base */
int addcurve(parser_data_t *par, char *); /* Adds curve to data base */
STmplist *findID(char *, STmplist *); /* Locates ID on linked list */
int unlinked(EN_Project *pr); /* Checks for unlinked nodes */
int getpumpparams(EN_Project *pr); /* Computes pump curve coeffs.*/
int getpatterns(EN_Project *pr); /* Gets pattern data from list*/
int getcurves(EN_Project *pr); /* Gets curve data from list */
int findmatch(char *, char *[]); /* Finds keyword in line */
int match(const char *, const char *); /* Checks for word match */
int gettokens(char *s, char** Tok, int maxToks, char *comment); /* Tokenizes input line */
int getfloat(char *, double *); /* Converts string to double */
double hour(char *, char *); /* Converts time to hours */
int setreport(EN_Project *pr, char *); /* Processes reporting command*/
void inperrmsg(EN_Project *pr, int,int,char *); /* Input error message */
int findmatch(char *, char *[]); /* Finds keyword in line */
int match(const char *, const char *); /* Checks for word match */
int gettokens(char *s, char** Tok, int maxToks,
char *comment); /* Tokenizes input line */
int getfloat(char *, double *); /* Converts string to double */
double hour(char *, char *); /* Converts time to hours */
int setreport(EN_Project *pr, char *); /* Processes reporting command*/
void inperrmsg(EN_Project *pr, int,int,char *); /* Input error message */
/* ---------- INPUT3.C -----------------*/
int juncdata(EN_Project *pr); /* Processes junction data */
@@ -104,22 +107,25 @@ int statusdata(EN_Project *pr); /* Processes link status dat
int reportdata(EN_Project *pr); /* Processes report options */
int timedata(EN_Project *pr); /* Processes time options */
int optiondata(EN_Project *pr); /* Processes analysis options */
int optionchoice(EN_Project *pr, int); /* Processes option choices */
int optionvalue(EN_Project *pr, int); /* Processes option values */
int getpumpcurve(EN_Project *pr, int); /* Constructs a pump curve */
int powercurve(double, double, double,/* Coeffs. of power pump curve*/
int optionchoice(EN_Project *pr, int); /* Processes option choices */
int optionvalue(EN_Project *pr, int); /* Processes option values */
int getpumpcurve(EN_Project *pr, int); /* Constructs a pump curve */
int powercurve(double, double, double, /* Coeffs. of power pump curve*/
double, double, double *,
double *, double *);
int valvecheck(EN_Project *pr, int, int, int); /* Checks valve placement */
void changestatus(EN_Network *net, int, StatType, double); /* Changes status of a link */
int valvecheck(EN_Project *pr, int, int, int); /* Checks valve placement */
void changestatus(EN_Network *net, int, StatType,
double); /* Changes status of a link */
/* -------------- RULES.C --------------*/
void initrules(rules_t *rules); /* Initializes rule base */
void addrule(parser_data_t *par, char *); /* Adds rule to rule base */
void addrule(parser_data_t *par, char *); /* Adds rule to rule base */
int allocrules(EN_Project *pr); /* Allocates memory for rule */
int ruledata(EN_Project *pr); /* Processes rule input data */
int checkrules(EN_Project *pr, long); /* Checks all rules */
int checkrules(EN_Project *pr, long); /* Checks all rules */
void freerules(EN_Project *pr); /* Frees rule base memory */
int writeRuleinInp(EN_Project *pr, FILE *f, /* Writes rule to an INP file */
int RuleIdx);
int writeRuleinInp(EN_Project *pr, FILE *f, int RuleIdx);
@@ -127,167 +133,147 @@ int writeRuleinInp(EN_Project *pr, FILE *f, int RuleIdx);
int writereport(EN_Project *pr); /* Writes formatted report */
void writelogo(EN_Project *pr); /* Writes program logo */
void writesummary(EN_Project *pr); /* Writes network summary */
void writehydstat(EN_Project *pr, int,double); /* Writes hydraulic status */
void writehydstat(EN_Project *pr, int,double); /* Writes hydraulic status */
void writeenergy(EN_Project *pr); /* Writes energy usage */
int writeresults(EN_Project *pr); /* Writes node/link results */
void writeheader(EN_Project *pr, int,int); /* Writes heading on report */
void writeline(EN_Project *pr, char *); /* Writes line to report file */
void writerelerr(EN_Project *pr, int, double); /* Writes convergence error */
void writeheader(EN_Project *pr, int,int); /* Writes heading on report */
void writeline(EN_Project *pr, char *); /* Writes line to report file */
void writerelerr(EN_Project *pr, int, double); /* Writes convergence error */
void writestatchange(EN_Project *pr, int,char,char); /* Writes link status change */
void writecontrolaction(EN_Project *pr, int, int); /* Writes control action taken*/
void writeruleaction(EN_Project *pr, int, char *); /* Writes rule action taken */
int writehydwarn(EN_Project *pr, int,double); /* Writes hydraulic warnings */
int writehydwarn(EN_Project *pr, int,double); /* Writes hydraulic warnings */
void writehyderr(EN_Project *pr, int); /* Writes hydraulic error msg.*/
int disconnected(EN_Project *pr); /* Checks for disconnections */
int disconnected(EN_Project *pr); /* Checks for disconnections */
void marknodes(EN_Project *pr, int, int *, char *); /* Identifies connected nodes */
void getclosedlink(EN_Project *pr, int, char *); /* Finds a disconnecting link */
void writelimits(EN_Project *pr, int,int); /* Writes reporting limits */
int checklimits(report_options_t *rep, double *,int,int); /* Checks variable limits */
int checklimits(report_options_t *rep, double *,
int,int); /* Checks variable limits */
void writetime(EN_Project *pr, char *); /* Writes current clock time */
char *clocktime(char *, long); /* Converts time to hrs:min */
char *fillstr(char *, char, int); /* Fills string with character*/
int getnodetype(EN_Network *net, int); /* Determines node type */
char *clocktime(char *, long); /* Converts time to hrs:min */
char *fillstr(char *, char, int); /* Fills string with character*/
int getnodetype(EN_Network *net, int); /* Determines node type */
/* --------- HYDRAUL.C -----------------*/
int openhyd(EN_Project *pr); /* Opens hydraulics solver */
/*** Updated 3/1/01 ***/
void inithyd(EN_Project *pr, int initFlags); /* Re-sets initial conditions */
int runhyd(EN_Project *pr, long *); /* Solves 1-period hydraulics */
int nexthyd(EN_Project *pr, long *); /* Moves to next time period */
void inithyd(EN_Project *pr, int initFlags); /* Re-sets initial conditions */
int runhyd(EN_Project *pr, long *); /* Solves 1-period hydraulics */
int nexthyd(EN_Project *pr, long *); /* Moves to next time period */
void closehyd(EN_Project *pr); /* Closes hydraulics solver */
int allocmatrix(EN_Project *pr); /* Allocates matrix coeffs. */
void freematrix(EN_Project *pr); /* Frees matrix coeffs. */
void initlinkflow(EN_Project *pr, int, char, double); /* Initializes link flow */
void setlinkflow(EN_Project *pr, int, double); /* Sets link flow via headloss*/
void setlinkstatus(EN_Project *pr, int, char, StatType *, double *); /* Sets link status */
void setlinksetting(EN_Project *pr, int, double, StatType *, double *); /* Sets pump/valve setting */
void initlinkflow(EN_Project *pr, int, char,
double); /* Initializes link flow */
void setlinkflow(EN_Project *pr, int, double); /* Sets link flow via headloss*/
void setlinkstatus(EN_Project *pr, int, char,
StatType *, double *); /* Sets link status */
void setlinksetting(EN_Project *pr, int, double,
StatType *, double *); /* Sets pump/valve setting */
void resistance(EN_Project *pr, int); /* Computes resistance coeff. */
void demands(EN_Project *pr); /* Computes current demands */
int controls(EN_Project *pr); /* Controls link settings */
long timestep(EN_Project *pr); /* Computes new time step */
int tanktimestep(EN_Project *pr, long *); /* Time till tanks fill/drain */
void controltimestep(EN_Project *pr, long *); /* Time till control action */
void ruletimestep(EN_Project *pr, long *); /* Time till rule action */
void addenergy(EN_Project *pr, long); /* Accumulates energy usage */
void getenergy(EN_Project *pr, int, double *, double *); /* Computes link energy use */
void tanklevels(EN_Project *pr, long); /* Computes new tank levels */
double tankvolume(EN_Project *pr, int,double); /* Finds tank vol. from grade */
double tankgrade(EN_Project *pr, int,double); /* Finds tank grade from vol. */
int netsolve(EN_Project *pr, int *,double *); /* Solves network equations */
int badvalve(EN_Project *pr, int); /* Checks for bad valve */
int valvestatus(EN_Project *pr); /* Updates valve status */
int linkstatus(EN_Project *pr); /* Updates link status */
StatType cvstatus(EN_Project *pr, StatType,double,double); /* Updates CV status */
StatType pumpstatus(EN_Project *pr, int,double); /* Updates pump status */
StatType prvstatus(EN_Project *pr, int,StatType,double,double,double); /* Updates PRV status */
StatType psvstatus(EN_Project *pr, int,StatType,double,double,double); /* Updates PSV status */
StatType fcvstatus(EN_Project *pr, int,StatType,double,double); /* Updates FCV status */
void tankstatus(EN_Project *pr, int,int,int); /* Checks if tank full/empty */
int pswitch(EN_Project *pr); /* Pressure switch controls */
double newflows(EN_Project *pr); /* Updates link flows */
void newcoeffs(EN_Project *pr); /* Computes matrix coeffs. */
void linkcoeffs(EN_Project *pr); /* Computes link coeffs. */
void nodecoeffs(EN_Project *pr); /* Computes node coeffs. */
void valvecoeffs(EN_Project *pr); /* Computes valve coeffs. */
void pipecoeff(EN_Project *pr, int); /* Computes pipe coeff. */
double DWcoeff(EN_Project *pr, int, double *); /* Computes D-W coeff. */
void pumpcoeff(EN_Project *pr, int); /* Computes pump coeff. */
int tanktimestep(EN_Project *pr, long *); /* Time till tanks fill/drain */
void controltimestep(EN_Project *pr, long *); /* Time till control action */
void ruletimestep(EN_Project *pr, long *); /* Time till rule action */
/*** Updated 10/25/00 ***/
/*** Updated 12/29/00 ***/
void curvecoeff(EN_Project *pr, int,double,double *,double *); /* Computes curve coeffs. */
void addenergy(EN_Project *pr, long); /* Accumulates energy usage */
void getenergy(EN_Project *pr, int, double *,
double *); /* Computes link energy use */
void gpvcoeff(EN_Project *pr, int iLink); /* Computes GPV coeff. */
void pbvcoeff(EN_Project *pr, int iLink); /* Computes PBV coeff. */
void tcvcoeff(EN_Project *pr, int iLink); /* Computes TCV coeff. */
void prvcoeff(EN_Project *pr, int iLink, int n1, int n2); /* Computes PRV coeff. */
void psvcoeff(EN_Project *pr, int iLink, int n1, int n2); /* Computes PSV coeff. */
void fcvcoeff(EN_Project *pr, int iLink, int n1, int n2); /* Computes FCV coeff. */
void emittercoeffs(EN_Project *pr); /* Computes emitter coeffs. */
double emitflowchange(EN_Project *pr, int); /* Computes new emitter flow */
void tanklevels(EN_Project *pr, long); /* Computes new tank levels */
double tankvolume(EN_Project *pr, int,double); /* Finds tank vol. from grade */
double tankgrade(EN_Project *pr, int,double); /* Finds tank grade from vol. */
/* ----------- HYDSOLVER.C - ----------*/
int hydsolve(EN_Project *pr, int *,double *); /* Solves network equations */
/* ----------- HYDCOEFFS.C --------------*/
void resistcoeff(EN_Project *pr, int k); /* Finds pipe flow resistance */
void hlosscoeff(EN_Project *pr, int k); /* Finds link head loss coeff */
void matrixcoeffs(EN_Project *pr); /* Finds hyd. matrix coeffs. */
/* ----------- SMATRIX.C ---------------*/
int createsparse(EN_Project *pr); /* Creates sparse matrix */
int allocsparse(EN_Project *pr); /* Allocates matrix memory */
void freesparse(EN_Project *pr); /* Frees matrix memory */
int buildlists(EN_Project *pr, int); /* Builds adjacency lists */
int paralink(EN_Project *pr, int, int, int); /* Checks for parallel links */
int buildlists(EN_Project *pr, int); /* Builds adjacency lists */
int paralink(EN_Project *pr, int, int, int); /* Checks for parallel links */
void xparalinks(EN_Project *pr); /* Removes parallel links */
void freelists(EN_Project *pr); /* Frees adjacency lists */
void countdegree(EN_Project *pr); /* Counts links at each node */
int reordernodes(EN_Project *pr); /* Finds a node re-ordering */
int mindegree(solver_t *s, int, int); /* Finds min. degree node */
int growlist(EN_Project *pr, int); /* Augments adjacency list */
int newlink(EN_Project *pr, Padjlist); /* Adds fill-ins for a node */
int linked(EN_Network *net, int, int); /* Checks if 2 nodes linked */
int addlink(EN_Network *net, int, int, int); /* Creates new fill-in */
int storesparse(EN_Project *pr, int); /* Stores sparse matrix */
int ordersparse(hydraulics_t *h, int); /* Orders matrix storage */
void transpose(int,int *,int *, /* Transposes sparse matrix */
int mindegree(solver_t *s, int, int); /* Finds min. degree node */
int growlist(EN_Project *pr, int); /* Augments adjacency list */
int newlink(EN_Project *pr, Padjlist); /* Adds fill-ins for a node */
int linked(EN_Network *net, int, int); /* Checks if 2 nodes linked */
int addlink(EN_Network *net, int, int, int); /* Creates new fill-in */
int storesparse(EN_Project *pr, int); /* Stores sparse matrix */
int ordersparse(hydraulics_t *h, int); /* Orders matrix storage */
void transpose(int,int *,int *, /* Transposes sparse matrix */
int *,int *,int *,int *,int *);
int linsolve(solver_t *s, int); /* via Cholesky factorization */
int linsolve(solver_t *s, int); /* Solves set of inear eqns. */
/* ----------- QUALITY.C ---------------*/
int openqual(EN_Project *pr); /* Opens WQ solver system */
void initqual(EN_Project *pr); /* Initializes WQ solver */
int runqual(EN_Project *pr, long *); /* Gets current WQ results */
int nextqual(EN_Project *pr, long *); /* Updates WQ by hyd.timestep */
int stepqual(EN_Project *pr, long *); /* Updates WQ by WQ time step */
int runqual(EN_Project *pr, long *); /* Gets current WQ results */
int nextqual(EN_Project *pr, long *); /* Updates WQ by hyd.timestep */
int stepqual(EN_Project *pr, long *); /* Updates WQ by WQ time step */
int closequal(EN_Project *pr); /* Closes WQ solver system */
int gethyd(EN_Project *pr, long *, long *); /* Gets next hyd. results */
int gethyd(EN_Project *pr, long *, long *); /* Gets next hyd. results */
char setReactflag(EN_Project *pr); /* Checks for reactive chem. */
void transport(EN_Project *pr, long); /* Transports mass in network */
void transport(EN_Project *pr, long); /* Transports mass in network */
void initsegs(EN_Project *pr); /* Initializes WQ segments */
void reorientsegs(EN_Project *pr); /* Re-orients WQ segments */
void updatesegs(EN_Project *pr, long); /* Updates quality in segments*/
void removesegs(EN_Project *pr, int); /* Removes a WQ segment */
void addseg(EN_Project *pr, int,double,double); /* Adds a WQ segment to pipe */
void accumulate(EN_Project *pr, long); /* Sums mass flow into node */
void updatenodes(EN_Project *pr, long); /* Updates WQ at nodes */
void sourceinput(EN_Project *pr, long); /* Computes source inputs */
void release(EN_Project *pr, long); /* Releases mass from nodes */
void updatetanks(EN_Project *pr, long); /* Updates WQ in tanks */
void updatesourcenodes(EN_Project *pr, long); /* Updates WQ at source nodes */
void tankmix1(EN_Project *pr, int, long); /* Complete mix tank model */
void tankmix2(EN_Project *pr, int, long); /* 2-compartment tank model */
void tankmix3(EN_Project *pr, int, long); /* FIFO tank model */
void tankmix4(EN_Project *pr, int, long); /* LIFO tank model */
double sourcequal(EN_Project *pr, Psource); /* Finds WQ input from source */
double avgqual(EN_Project *pr, int); /* Finds avg. quality in pipe */
void updatesegs(EN_Project *pr, long); /* Updates quality in segments*/
void removesegs(EN_Project *pr, int); /* Removes a WQ segment */
void addseg(EN_Project *pr, int,double,double); /* Adds a WQ segment to pipe */
void accumulate(EN_Project *pr, long); /* Sums mass flow into node */
void updatenodes(EN_Project *pr, long); /* Updates WQ at nodes */
void sourceinput(EN_Project *pr, long); /* Computes source inputs */
void release(EN_Project *pr, long); /* Releases mass from nodes */
void updatetanks(EN_Project *pr, long); /* Updates WQ in tanks */
void updatesourcenodes(EN_Project *pr, long); /* Updates WQ at source nodes */
void tankmix1(EN_Project *pr, int, long); /* Complete mix tank model */
void tankmix2(EN_Project *pr, int, long); /* 2-compartment tank model */
void tankmix3(EN_Project *pr, int, long); /* FIFO tank model */
void tankmix4(EN_Project *pr, int, long); /* LIFO tank model */
double sourcequal(EN_Project *pr, Psource); /* Finds WQ input from source */
double avgqual(EN_Project *pr, int); /* Finds avg. quality in pipe */
void ratecoeffs(EN_Project *pr); /* Finds wall react. coeffs. */
double piperate(EN_Project *pr, int); /* Finds wall react. coeff. */
double pipereact(EN_Project *pr, int,double,double,long);/* Reacts water in a pipe */
double tankreact(EN_Project *pr, double,double,double,long); /* Reacts water in a tank */
double bulkrate(EN_Project *pr, double,double,double); /* Finds bulk reaction rate */
double wallrate(EN_Project *pr, double,double,double,double);/* Finds wall reaction rate */
double piperate(EN_Project *pr, int); /* Finds wall react. coeff. */
double pipereact(EN_Project *pr, int,double,
double,long); /* Reacts water in a pipe */
double tankreact(EN_Project *pr, double,double,
double,long); /* Reacts water in a tank */
double bulkrate(EN_Project *pr, double,double,
double); /* Finds bulk reaction rate */
double wallrate(EN_Project *pr, double,double,
double,double); /* Finds wall reaction rate */
/* ------------ OUTPUT.C ---------------*/
int savenetdata(EN_Project *pr); /* Saves basic data to file */
int savehyd(EN_Project *pr, long *); /* Saves hydraulic solution */
int savehydstep(EN_Project *pr, long *); /* Saves hydraulic timestep */
int savehyd(EN_Project *pr, long *); /* Saves hydraulic solution */
int savehydstep(EN_Project *pr, long *); /* Saves hydraulic timestep */
int saveenergy(EN_Project *pr); /* Saves energy usage */
int readhyd(EN_Project *pr, long *); /* Reads hydraulics from file */
int readhydstep(FILE *hydFile, long *); /* Reads time step from file */
int readhyd(EN_Project *pr, long *); /* Reads hydraulics from file */
int readhydstep(FILE *hydFile, long *); /* Reads time step from file */
int saveoutput(EN_Project *pr); /* Saves results to file */
int nodeoutput(EN_Project *pr, int, REAL4 *, double); /* Saves node results to file */
int linkoutput(EN_Project *pr, int, REAL4 *, double); /* Saves link results to file */
int nodeoutput(EN_Project *pr, int, REAL4 *,
double); /* Saves node results to file */
int linkoutput(EN_Project *pr, int, REAL4 *,
double); /* Saves link results to file */
int savefinaloutput(EN_Project *pr); /* Finishes saving output */
int savetimestat(EN_Project *pr, REAL4 *, HdrType); /* Saves time stats to file */
int savenetreacts(EN_Project *pr, double, double,double, double);
/* Saves react. rates to file */
int savetimestat(EN_Project *pr, REAL4 *,
HdrType); /* Saves time stats to file */
int savenetreacts(EN_Project *pr, double,
double,double, double); /* Saves react. rates to file */
int saveepilog(EN_Project *pr); /* Saves output file epilog */
/* ------------ INPFILE.C --------------*/
int saveinpfile(EN_Project *pr, char *); /* Saves network to text file */
int saveinpfile(EN_Project *pr, char *); /* Saves network to text file */
#endif

933
src/hydcoeffs.c Normal file
View File

@@ -0,0 +1,933 @@
/*
*********************************************************************
HYDCOEFFS.C -- hydraulic coefficients for the EPANET Program
*******************************************************************
*/
#include <stdio.h>
#include <string.h>
#ifndef __APPLE__
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#include <math.h>
#include "types.h"
#include "funcs.h"
// Constants used for computing Darcy-Weisbach friction factor
const double A1 = 0.314159265359e04; // 1000*PI
const double A2 = 0.157079632679e04; // 500*PI
const double A3 = 0.502654824574e02; // 16*PI
const double A4 = 6.283185307; // 2*PI
const double A8 = 4.61841319859; // 5.74*(PI/4)^.9
const double A9 = -8.685889638e-01; // -2/ln(10)
const double AA = -1.5634601348; // -2*.9*2/ln(10)
const double AB = 3.28895476345e-03; // 5.74/(4000^.9)
const double AC = -5.14214965799e-03; // AA*AB
// External functions
//void resistcoeff(EN_Project *pr, int k);
//void hlosscoeff(EN_Project *pr, int k);
//void matrixcoeffs(EN_Project *pr);
// Local functions
static void linkcoeffs(EN_Project *pr);
static void nodecoeffs(EN_Project *pr);
static void valvecoeffs(EN_Project *pr);
static void emittercoeffs(EN_Project *pr);
static void pipecoeff(EN_Project *pr, int k);
static void DWpipecoeff(EN_Project *pr, int k);
static double frictionFactor(EN_Project *pr, int k, double *dfdq);
static void pumpcoeff(EN_Project *pr, int k);
static void curvecoeff(EN_Project *pr, int i, double q, double *h0, double *r);
static void valvecoeff(EN_Project *pr, int k);
static void gpvcoeff(EN_Project *pr, int k);
static void pbvcoeff(EN_Project *pr, int k);
static void tcvcoeff(EN_Project *pr, int k);
static void prvcoeff(EN_Project *pr, int k, int n1, int n2);
static void psvcoeff(EN_Project *pr, int k, int n1, int n2);
static void fcvcoeff(EN_Project *pr, int k, int n1, int n2);
void resistcoeff(EN_Project *pr, int k)
/*
**--------------------------------------------------------------------
** Input: k = link index
** Output: none
** Purpose: computes link flow resistance coefficient
**--------------------------------------------------------------------
*/
{
double e, d, L;
EN_Network *net = &pr->network;
hydraulics_t *hyd = &pr->hydraulics;
Slink *link = &net->Link[k];
switch (link->Type) {
// ... Link is a pipe. Compute resistance based on headloss formula.
// Friction factor for D-W formula gets included during head loss
// calculation.
case EN_CVPIPE:
case EN_PIPE:
e = link->Kc; // Roughness coeff.
d = link->Diam; // Diameter
L = link->Len; // Length
switch (hyd->Formflag)
{
case HW:
link->R = 4.727*L / pow(e, hyd->Hexp) / pow(d, 4.871);
break;
case DW:
link->R = L / 2.0 / 32.2 / d / SQR(PI*SQR(d) / 4.0);
break;
case CM:
link->R = SQR(4.0*e / (1.49*PI*d*d)) * pow((d / 4.0), -1.333)*L;
}
break;
// ... Link is a pump. Use huge resistance.
case EN_PUMP:
link->R = CBIG;
break;
// ... For all other links (e.g. valves) use a small resistance
default:
link->R = CSMALL;
break;
}
}
void hlosscoeff(EN_Project *pr, int k)
/*
**--------------------------------------------------------------
** Input: k = link index
** Output: none
** Purpose: computes P and Y coefficients for a link
**--------------------------------------------------------------
*/
{
EN_Network *net = &pr->network;
hydraulics_t *hyd = &pr->hydraulics;
solver_t *sol = &hyd->solver;
Slink *link = &net->Link[k];
switch (link->Type)
{
case EN_CVPIPE:
case EN_PIPE:
pipecoeff(pr, k);
break;
case EN_PUMP:
pumpcoeff(pr, k);
break;
case EN_PBV:
pbvcoeff(pr, k);
break;
case EN_TCV:
tcvcoeff(pr, k);
break;
case EN_GPV:
gpvcoeff(pr, k);
break;
case EN_FCV:
case EN_PRV:
case EN_PSV:
if (hyd->LinkSetting[k] == MISSING) {
valvecoeff(pr, k);
}
else sol->P[k] = 0.0;
}
}
void matrixcoeffs(EN_Project *pr)
/*
**--------------------------------------------------------------
** Input: none
** Output: none
** Purpose: computes coefficients of linearized network eqns.
**--------------------------------------------------------------
*/
{
hydraulics_t *hyd = &pr->hydraulics;
solver_t *sol = &hyd->solver;
EN_Network *net = &pr->network;
memset(sol->Aii, 0, (net->Nnodes + 1) * sizeof(double));
memset(sol->Aij, 0, (hyd->Ncoeffs + 1) * sizeof(double));
memset(sol->F, 0, (net->Nnodes + 1) * sizeof(double));
memset(hyd->X_tmp, 0, (net->Nnodes + 1) * sizeof(double));
linkcoeffs(pr);
emittercoeffs(pr);
nodecoeffs(pr);
valvecoeffs(pr);
}
void linkcoeffs(EN_Project *pr)
/*
**--------------------------------------------------------------
** Input: none
** Output: none
** Purpose: computes matrix coefficients for links
**--------------------------------------------------------------
*/
{
int k, n1, n2;
EN_Network *net = &pr->network;
hydraulics_t *hyd = &pr->hydraulics;
solver_t *sol = &hyd->solver;
Slink *link;
// Examine each link of network */
for (k = 1; k <= net->Nlinks; k++)
{
if (sol->P[k] == 0.0) continue;
link = &net->Link[k];
n1 = link->N1; // Start node of link
n2 = link->N2; // End node of link
// Update net nodal inflows (X), solution matrix (A) and RHS array (F)
// (Use covention that flow out of node is (-), flow into node is (+))
hyd->X_tmp[n1] -= hyd->LinkFlows[k];
hyd->X_tmp[n2] += hyd->LinkFlows[k];
// Off-diagonal coeff.
sol->Aij[sol->Ndx[k]] -= sol->P[k];
// Node n1 is junction
if (n1 <= net->Njuncs)
{
sol->Aii[sol->Row[n1]] += sol->P[k]; // Diagonal coeff.
sol->F[sol->Row[n1]] += sol->Y[k]; // RHS coeff.
}
// Node n1 is a tank
else {
sol->F[sol->Row[n2]] += (sol->P[k] * hyd->NodeHead[n1]);
}
// Node n2 is junction
if (n2 <= net->Njuncs) {
sol->Aii[sol->Row[n2]] += sol->P[k]; // Diagonal coeff.
sol->F[sol->Row[n2]] -= sol->Y[k]; // RHS coeff.
}
// Node n2 is a tank
else {
sol->F[sol->Row[n1]] += (sol->P[k] * hyd->NodeHead[n2]);
}
}
}
void nodecoeffs(EN_Project *pr)
/*
**----------------------------------------------------------------
** Input: none
** Output: none
** Purpose: completes calculation of nodal flow imbalance (X)
** & flow correction (F) arrays
**----------------------------------------------------------------
*/
{
int i;
hydraulics_t *hyd = &pr->hydraulics;
solver_t *sol = &hyd->solver;
EN_Network *net = &pr->network;
// For junction nodes, subtract demand flow from net
// flow imbalance & add imbalance to RHS array F.
for (i = 1; i <= net->Njuncs; i++)
{
hyd->X_tmp[i] -= hyd->NodeDemand[i];
sol->F[sol->Row[i]] += hyd->X_tmp[i];
}
}
void valvecoeffs(EN_Project *pr)
/*
**--------------------------------------------------------------
** Input: none
** Output: none
** Purpose: computes matrix coeffs. for PRVs, PSVs & FCVs
** whose status is not fixed to OPEN/CLOSED
**--------------------------------------------------------------
*/
{
int i, k, n1, n2;
hydraulics_t *hyd = &pr->hydraulics;
EN_Network *net = &pr->network;
Slink *link;
Svalve *valve;
// Examine each valve
for (i = 1; i <= net->Nvalves; i++)
{
valve = &net->Valve[i];
k = valve->Link; // Link index of valve
link = &net->Link[k];
if (hyd->LinkSetting[k] == MISSING) {
continue; // Valve status fixed
}
n1 = link->N1; // Start & end nodes
n2 = link->N2;
switch (link->Type) // Call valve-specific function
{
case EN_PRV:
prvcoeff(pr, k, n1, n2);
break;
case EN_PSV:
psvcoeff(pr, k, n1, n2);
break;
case EN_FCV:
fcvcoeff(pr, k, n1, n2);
break;
default: continue;
}
}
}
void emittercoeffs(EN_Project *pr)
/*
**--------------------------------------------------------------
** Input: none
** Output: none
** Purpose: computes matrix coeffs. for emitters
**
** Note: Emitters consist of a fictitious pipe connected to
** a fictitious reservoir whose elevation equals that
** of the junction. The headloss through this pipe is
** Ke*(Flow)^hyd->Qexp, where Ke = emitter headloss coeff.
**--------------------------------------------------------------
*/
{
int i;
double ke;
double p;
double q;
double y;
double z;
hydraulics_t *hyd = &pr->hydraulics;
solver_t *sol = &hyd->solver;
EN_Network *net = &pr->network;
Snode *node;
for (i = 1; i <= net->Njuncs; i++)
{
node = &net->Node[i];
if (node->Ke == 0.0) {
continue;
}
ke = MAX(CSMALL, node->Ke); // emitter coeff.
q = hyd->EmitterFlows[i]; // emitter flow
z = ke * pow(ABS(q), hyd->Qexp); // emitter head loss
p = hyd->Qexp * z / ABS(q); // head loss gradient
if (p < hyd->RQtol) {
p = 1.0 / hyd->RQtol;
}
else {
p = 1.0 / p; // inverse head loss gradient
}
y = SGN(q)*z*p; // head loss / gradient
sol->Aii[sol->Row[i]] += p; // addition to main diagonal
sol->F[sol->Row[i]] += y + p * node->El; // addition to r.h.s.
hyd->X_tmp[i] -= q; // addition to net node inflow
}
}
void pipecoeff(EN_Project *pr, int k)
/*
**--------------------------------------------------------------
** Input: k = link index
** Output: none
** Purpose: computes P & Y coefficients for pipe k
**
** P = inverse head loss gradient = 1/(dh/dQ)
** Y = flow correction term = h*P
**--------------------------------------------------------------
*/
{
double hpipe, // Normal head loss
hml, // Minor head loss
ml, // Minor loss coeff.
p, // q*(dh/dq)
q, // Abs. value of flow
r; // Resistance coeff.
hydraulics_t *hyd = &pr->hydraulics;
solver_t *sol = &hyd->solver;
Slink *link = &pr->network.Link[k];
// For closed pipe use headloss formula: h = CBIG*q
if (hyd->LinkStatus[k] <= CLOSED)
{
sol->P[k] = 1.0 / CBIG;
sol->Y[k] = hyd->LinkFlows[k];
return;
}
// ... head loss formula is Darcy-Weisbach
if (hyd->Formflag == DW) {
DWpipecoeff(pr, k);
return;
}
// Evaluate headloss coefficients
q = ABS(hyd->LinkFlows[k]); // Absolute flow
ml = link->Km; // Minor loss coeff.
r = link->R; // Resistance coeff.
// Use large P coefficient for small flow resistance product
if ( (r+ml)*q < hyd->RQtol)
{
sol->P[k] = 1.0 / hyd->RQtol;
sol->Y[k] = hyd->LinkFlows[k] / hyd->Hexp;
return;
}
// Compute P and Y coefficients
hpipe = r*pow(q, hyd->Hexp); // Friction head loss
p = hyd->Hexp*hpipe; // Q*dh(friction)/dQ
if (ml > 0.0)
{
hml = ml*q*q; // Minor head loss
p += 2.0*hml; // Q*dh(Total)/dQ
}
else hml = 0.0;
p = hyd->LinkFlows[k] / p; // 1 / (dh/dQ)
sol->P[k] = ABS(p);
sol->Y[k] = p*(hpipe + hml);
}
void DWpipecoeff(EN_Project *pr, int k)
/*
**--------------------------------------------------------------
** Input: k = link index
** Output: none
** Purpose: computes pipe head loss coeffs. for Darcy-Weisbach
** formula.
**--------------------------------------------------------------
*/
{
hydraulics_t *hyd = &pr->hydraulics;
solver_t *sol = &hyd->solver;
Slink *link = &pr->network.Link[k];
double q = ABS(hyd->LinkFlows[k]);
double dfdq = 0.0;
double r, r1, f, ml, p, hloss;
ml = link->Km; // Minor loss coeff.
r = link->R; // Resistance coeff.
f = frictionFactor(pr,k,&dfdq); // D-W friction factor
r1 = f*r+ml;
// Use large P coefficient for small flow resistance product
if (r1*q < hyd->RQtol)
{
sol->P[k] = 1.0/hyd->RQtol;
sol->Y[k] = hyd->LinkFlows[k]/hyd->Hexp;
return;
}
// Compute P and Y coefficients
hloss = r1*SQR(q); // Total head loss
p = 2.0*r1*q; // |dHloss/dQ|
// + dfdq*r*q*q; // Ignore df/dQ term
p = 1.0 / p;
sol->P[k] = p;
sol->Y[k] = SGN(hyd->LinkFlows[k]) * hloss * p;
}
double frictionFactor(EN_Project *pr, int k, double *dfdq)
/*
**--------------------------------------------------------------
** Input: k = link index
** Output: returns friction factor and
** replaces dfdq (derivative of f w.r.t. flow)
** Purpose: computes Darcy-Weisbach friction factor and its
** derivative as a function of Reynolds Number (Re).
**
** Note: Current formulas for dfdq need to be corrected
** so dfdq returned as 0.
**--------------------------------------------------------------
*/
{
double q, // Abs. value of flow
f; // Friction factor
double x1,x2,x3,x4,
y1,y2,y3,
fa,fb,r;
double s,w;
hydraulics_t *hyd = &pr->hydraulics;
Slink *link = &pr->network.Link[k];
*dfdq = 0.0;
if (link->Type > EN_PIPE)
return(1.0); // Only apply to pipes
q = ABS(hyd->LinkFlows[k]);
s = hyd->Viscos * link->Diam;
w = q/s; // w = Re(Pi/4)
// For Re >= 4000 use Colebrook Formula
if (w >= A1)
{
y1 = A8/pow(w,0.9);
y2 = link->Kc/(3.7*link->Diam) + y1;
y3 = A9*log(y2);
f = 1.0/SQR(y3);
/* *dfdq = (2.0+AA*y1/(y2*y3))*f; */ /* df/dq */
}
// For Re > 2000 use Interpolation Formula
else if (w > A2)
{
y2 = link->Kc/(3.7*link->Diam) + AB;
y3 = A9*log(y2);
fa = 1.0/SQR(y3);
fb = (2.0+AC/(y2*y3))*fa;
r = w/A2;
x1 = 7.0*fa - fb;
x2 = 0.128 - 17.0*fa + 2.5*fb;
x3 = -0.128 + 13.0*fa - (fb+fb);
x4 = r*(0.032 - 3.0*fa + 0.5*fb);
f = x1 + r*(x2 + r*(x3+x4));
/* *dfdq = (x1 + x1 + r*(3.0*x2 + r*(4.0*x3 + 5.0*x4))); */
}
// For Re > 8 (Laminar Flow) use Hagen-Poiseuille Formula
else if (w > A4)
{
f = A3*s/q; // 16 * PI * Viscos * Diam / Flow
/* *dfdq = A3*s; */
}
else
{
f = 8.0;
*dfdq = 0.0;
}
return(f);
}
void pumpcoeff(EN_Project *pr, int k)
/*
**--------------------------------------------------------------
** Input: k = link index
** Output: none
** Purpose: computes P & Y coeffs. for pump in link k
**--------------------------------------------------------------
*/
{
int p; // Pump index
double h0, // Shutoff head
q, // Abs. value of flow
r, // Flow resistance coeff.
n; // Flow exponent coeff.
hydraulics_t *hyd = &pr->hydraulics;
solver_t *sol = &hyd->solver;
double setting = hyd->LinkSetting[k];
Spump *pump;
// Use high resistance pipe if pump closed or cannot deliver head
if (hyd->LinkStatus[k] <= CLOSED || setting == 0.0) {
sol->P[k] = 1.0 / CBIG;
sol->Y[k] = hyd->LinkFlows[k];
return;
}
q = ABS(hyd->LinkFlows[k]);
q = MAX(q, TINY);
// Obtain reference to pump object
p = findpump(&pr->network, k);
pump = &pr->network.Pump[p];
// Get pump curve coefficients for custom pump curve.
if (pump->Ptype == CUSTOM)
{
// Find intercept (h0) & slope (r) of pump curve
// line segment which contains speed-adjusted flow.
curvecoeff(pr, pump->Hcurve, q / setting, &h0, &r);
// Determine head loss coefficients.
pump->H0 = -h0;
pump->R = -r;
pump->N = 1.0;
}
// Adjust head loss coefficients for pump speed.
h0 = SQR(setting) * pump->H0;
n = pump->N;
r = pump->R * pow(setting, 2.0 - n);
if (n != 1.0) {
r = n * r * pow(q, n - 1.0);
}
// Compute inverse headloss gradient (P) and flow correction factor (Y)
sol->P[k] = 1.0 / MAX(r, hyd->RQtol);
sol->Y[k] = hyd->LinkFlows[k] / n + sol->P[k] * h0;
}
void curvecoeff(EN_Project *pr, int i, double q, double *h0, double *r)
/*
**-------------------------------------------------------------------
** Input: i = curve index
** q = flow rate
** Output: *h0 = head at zero flow (y-intercept)
** *r = dHead/dFlow (slope)
** Purpose: computes intercept and slope of head v. flow curve
** at current flow.
**-------------------------------------------------------------------
*/
{
int k1, k2, npts;
double *x, *y;
Scurve *curve;
// Remember that curve is stored in untransformed units
q *= pr->Ucf[FLOW];
curve = &pr->network.Curve[i];
x = curve->X; // x = flow
y = curve->Y; // y = head
npts = curve->Npts;
// Find linear segment of curve that brackets flow q
k2 = 0;
while (k2 < npts && x[k2] < q)
k2++;
if (k2 == 0)
k2++;
else if (k2 == npts)
k2--;
k1 = k2 - 1;
// Compute slope and intercept of this segment
*r = (y[k2] - y[k1]) / (x[k2] - x[k1]);
*h0 = y[k1] - (*r)*x[k1];
// Convert units
*h0 = (*h0) / pr->Ucf[HEAD];
*r = (*r) * pr->Ucf[FLOW] / pr->Ucf[HEAD];
}
void gpvcoeff(EN_Project *pr, int k)
/*
**--------------------------------------------------------------
** Input: k = link index
** Output: none
** Purpose: computes P & Y coeffs. for general purpose valve
**--------------------------------------------------------------
*/
{
double h0, // Headloss curve intercept
q, // Abs. value of flow
r; // Flow resistance coeff.
hydraulics_t *hyd = &pr->hydraulics;
solver_t *sol = &hyd->solver;
// Treat as a pipe if valve closed
if (hyd->LinkStatus[k] == CLOSED) {
valvecoeff(pr, k);
}
// Otherwise utilize headloss curve
// whose index is stored in K
else {
// Find slope & intercept of headloss curve.
q = ABS(hyd->LinkFlows[k]);
q = MAX(q, TINY);
curvecoeff(pr, (int)ROUND(hyd->LinkSetting[k]), q, &h0, &r);
// Compute inverse headloss gradient (P)
// and flow correction factor (Y).
sol->P[k] = 1.0 / MAX(r, hyd->RQtol);
sol->Y[k] = sol->P[k] * (h0 + r*q) * SGN(hyd->LinkFlows[k]);
}
}
void pbvcoeff(EN_Project *pr, int k)
/*
**--------------------------------------------------------------
** Input: k = link index
** Output: none
** Purpose: computes P & Y coeffs. for pressure breaker valve
**--------------------------------------------------------------
*/
{
hydraulics_t *hyd = &pr->hydraulics;
solver_t *sol = &hyd->solver;
Slink *link = &pr->network.Link[k];
// If valve fixed OPEN or CLOSED then treat as a pipe
if (hyd->LinkSetting[k] == MISSING || hyd->LinkSetting[k] == 0.0) {
valvecoeff(pr, k);
}
// If valve is active
else {
// Treat as a pipe if minor loss > valve setting
if (link->Km * SQR(hyd->LinkFlows[k]) > hyd->LinkSetting[k]) {
valvecoeff(pr, k);
}
// Otherwise force headloss across valve to be equal to setting
else {
sol->P[k] = CBIG;
sol->Y[k] = hyd->LinkSetting[k] * CBIG;
}
}
}
void tcvcoeff(EN_Project *pr, int k)
/*
**--------------------------------------------------------------
** Input: k = link index
** Output: none
** Purpose: computes P & Y coeffs. for throttle control valve
**--------------------------------------------------------------
*/
{
double km;
hydraulics_t *hyd = &pr->hydraulics;
Slink *link = &pr->network.Link[k];
// Save original loss coeff. for open valve
km = link->Km;
// If valve not fixed OPEN or CLOSED, compute its loss coeff.
if (hyd->LinkSetting[k] != MISSING) {
link->Km = 0.02517 * hyd->LinkSetting[k] / (SQR(link->Diam)*SQR(link->Diam));
}
// Then apply usual valve formula
valvecoeff(pr, k);
// Restore original loss coeff.
link->Km = km;
}
void prvcoeff(EN_Project *pr, int k, int n1, int n2)
/*
**--------------------------------------------------------------
** Input: k = link index
** n1 = upstream node of valve
** n2 = downstream node of valve
** Output: none
** Purpose: computes solution matrix coeffs. for pressure
** reducing valves
**--------------------------------------------------------------
*/
{
int i, j; // Rows of solution matrix
double hset; // Valve head setting
hydraulics_t *hyd = &pr->hydraulics;
solver_t *sol = &hyd->solver;
i = sol->Row[n1]; // Matrix rows of nodes
j = sol->Row[n2];
hset = pr->network.Node[n2].El +
hyd->LinkSetting[k]; // Valve setting
if (hyd->LinkStatus[k] == ACTIVE)
{
// Set coeffs. to force head at downstream
// node equal to valve setting & force flow
// to equal to flow imbalance at downstream node.
sol->P[k] = 0.0;
sol->Y[k] = hyd->LinkFlows[k] + hyd->X_tmp[n2]; // Force flow balance
sol->F[j] += (hset * CBIG); // Force head = hset
sol->Aii[j] += CBIG; // at downstream node
if (hyd->X_tmp[n2] < 0.0) {
sol->F[i] += hyd->X_tmp[n2];
}
return;
}
// For OPEN, CLOSED, or XPRESSURE valve
// compute matrix coeffs. using the valvecoeff() function.
valvecoeff(pr, k);
sol->Aij[sol->Ndx[k]] -= sol->P[k];
sol->Aii[i] += sol->P[k];
sol->Aii[j] += sol->P[k];
sol->F[i] += (sol->Y[k] - hyd->LinkFlows[k]);
sol->F[j] -= (sol->Y[k] - hyd->LinkFlows[k]);
}
void psvcoeff(EN_Project *pr, int k, int n1, int n2)
/*
**--------------------------------------------------------------
** Input: k = link index
** n1 = upstream node of valve
** n2 = downstream node of valve
** Output: none
** Purpose: computes solution matrix coeffs. for pressure
** sustaining valve
**--------------------------------------------------------------
*/
{
int i, j; // Rows of solution matrix
double hset; // Valve head setting
hydraulics_t *hyd = &pr->hydraulics;
solver_t *sol = &hyd->solver;
i = sol->Row[n1]; // Matrix rows of nodes
j = sol->Row[n2];
hset = pr->network.Node[n1].El +
hyd->LinkSetting[k]; // Valve setting
if (hyd->LinkStatus[k] == ACTIVE)
{
// Set coeffs. to force head at upstream
// node equal to valve setting & force flow
// equal to flow imbalance at upstream node.
sol->P[k] = 0.0;
sol->Y[k] = hyd->LinkFlows[k] - hyd->X_tmp[n1]; // Force flow balance
sol->F[i] += (hset * CBIG); // Force head = hset
sol->Aii[i] += CBIG; // at upstream node
if (hyd->X_tmp[n1] > 0.0) {
sol->F[j] += hyd->X_tmp[n1];
}
return;
}
// For OPEN, CLOSED, or XPRESSURE valve
// compute matrix coeffs. using the valvecoeff() function.
valvecoeff(pr, k);
sol->Aij[sol->Ndx[k]] -= sol->P[k];
sol->Aii[i] += sol->P[k];
sol->Aii[j] += sol->P[k];
sol->F[i] += (sol->Y[k] - hyd->LinkFlows[k]);
sol->F[j] -= (sol->Y[k] - hyd->LinkFlows[k]);
}
void fcvcoeff(EN_Project *pr, int k, int n1, int n2)
/*
**--------------------------------------------------------------
** Input: k = link index
** n1 = upstream node of valve
** n2 = downstream node of valve
** Output: none
** Purpose: computes solution matrix coeffs. for flow control
** valve
**--------------------------------------------------------------
*/
{
int i, j; // Rows in solution matrix
double q; // Valve flow setting
hydraulics_t *hyd = &pr->hydraulics;
solver_t *sol = &hyd->solver;
q = hyd->LinkSetting[k];
i = hyd->solver.Row[n1];
j = hyd->solver.Row[n2];
// If valve active, break network at valve and treat
// flow setting as external demand at upstream node
// and external supply at downstream node.
if (hyd->LinkStatus[k] == ACTIVE)
{
hyd->X_tmp[n1] -= q;
sol->F[i] -= q;
hyd->X_tmp[n2] += q;
sol->F[j] += q;
sol->P[k] = 1.0 / CBIG;
sol->Aij[sol->Ndx[k]] -= sol->P[k];
sol->Aii[i] += sol->P[k];
sol->Aii[j] += sol->P[k];
sol->Y[k] = hyd->LinkFlows[k] - q;
}
// Otherwise treat valve as an open pipe
else
{
valvecoeff(pr, k);
sol->Aij[sol->Ndx[k]] -= sol->P[k];
sol->Aii[i] += sol->P[k];
sol->Aii[j] += sol->P[k];
sol->F[i] += (sol->Y[k] - hyd->LinkFlows[k]);
sol->F[j] -= (sol->Y[k] - hyd->LinkFlows[k]);
}
}
void valvecoeff(EN_Project *pr, int k)
/*
**--------------------------------------------------------------
** Input: k = link index
** Output: none
** Purpose: computes solution matrix coeffs. for a completely
** open, closed, or throttled control valve.
**--------------------------------------------------------------
*/
{
double p;
EN_Network *net = &pr->network;
hydraulics_t *hyd = &pr->hydraulics;
solver_t *sol = &hyd->solver;
Slink *link = &net->Link[k];
double flow = hyd->LinkFlows[k];
// Valve is closed. Use a very small matrix coeff.
if (hyd->LinkStatus[k] <= CLOSED)
{
sol->P[k] = 1.0 / CBIG;
sol->Y[k] = flow;
return;
}
// Account for any minor headloss through the valve
if (link->Km > 0.0)
{
p = 2.0 * link->Km * fabs(flow);
if (p < hyd->RQtol) {
p = hyd->RQtol;
}
sol->P[k] = 1.0 / p;
sol->Y[k] = flow / 2.0;
}
else
{
sol->P[k] = 1.0 / hyd->RQtol;
sol->Y[k] = flow;
}
}

File diff suppressed because it is too large Load Diff

1049
src/hydsolver.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -618,6 +618,12 @@ int saveinpfile(EN_Project *pr, char *fname)
fprintf(f, "\n CHECKFREQ %-d", hyd->CheckFreq);
fprintf(f, "\n MAXCHECK %-d", hyd->MaxCheck);
fprintf(f, "\n DAMPLIMIT %-.8f", hyd->DampLimit);
if (hyd->HeadErrorLimit > 0.0) {
fprintf(f, "\n HEADERROR %-.8f", hyd->HeadErrorLimit * pr->Ucf[HEAD]);
}
if (hyd->FlowChangeLimit > 0.0) {
fprintf(f, "\n FLOWCHANGE %-.8f", hyd->FlowChangeLimit * pr->Ucf[FLOW]);
}
/* Write [REPORT] section */

View File

@@ -40,10 +40,9 @@ AUTHOR: L. Rossman
--------------------- Module Global Variables ----------------------
*/
#define MAXITER \
200 /* Default max. # hydraulic iterations */
#define HACC 0.001 /* Default hydraulics convergence ratio */
#define HTOL 0.0005 /* Default hydraulic head tolerance (ft) */
#define MAXITER 200 /* Default max. # hydraulic iterations */
#define HACC 0.001 /* Default hydraulics convergence ratio */
#define HTOL 0.0005 /* Default hydraulic head tolerance (ft) */
/*** Updated 11/19/01 ***/
#define QTOL 0.0001 /* Default flow rate tolerance (cfs) */
@@ -62,8 +61,7 @@ AUTHOR: L. Rossman
#define RQTOL 1E-7 /* Default low flow resistance tolerance */
#define CHECKFREQ 2 /* Default status check frequency */
#define MAXCHECK 10 /* Default # iterations for status checks */
#define DAMPLIMIT \
0 /* Default damping threshold */
#define DAMPLIMIT 0 /* Default damping threshold */
extern char *Fldname[]; /* Defined in enumstxt.h in EPANET.C */
extern char *RptFlowUnitsTxt[];
@@ -119,19 +117,23 @@ void setdefaults(EN_Project *pr)
strncpy(qu->ChemUnits, u_MGperL, MAXID);
strncpy(par->DefPatID, DEFPATID, MAXID);
out->Hydflag = SCRATCH; /* No external hydraulics file */
qu->Qualflag = NONE; /* No quality simulation */
qu->Qualflag = NONE; /* No quality simulation */
hyd->Formflag = HW; /* Use Hazen-Williams formula */
par->Unitsflag = US; /* US unit system */
par->Flowflag = GPM; /* Flow units are gpm */
par->Pressflag = PSI; /* Pressure units are psi */
rep->Tstatflag = SERIES; /* Generate time series output */
pr->Warnflag = FALSE; /* Warning flag is off */
hyd->Htol = HTOL; /* Default head tolerance */
hyd->Qtol = QTOL; /* Default flow tolerance */
hyd->Hacc = HACC; /* Default hydraulic accuracy */
hyd->Htol = HTOL; /* Default head tolerance */
hyd->Qtol = QTOL; /* Default flow tolerance */
hyd->Hacc = HACC; /* Default hydraulic accuracy */
hyd->FlowChangeLimit = 0.0; /* Default flow change limit */
hyd->HeadErrorLimit = 0.0; /* Default head error limit */
qu->Ctol = MISSING; /* No pre-set quality tolerance */
hyd->MaxIter = MAXITER; /* Default max. hydraulic trials */
hyd->ExtraIter = -1; /* Stop if network unbalanced */
hyd->MaxIter = MAXITER; /* Default max. hydraulic trials */
hyd->ExtraIter = -1; /* Stop if network unbalanced */
time->Dur = 0; /* 0 sec duration (steady state) */
time->Tstart = 0; /* Starting time of day */
time->Pstart = 0; /* Starting pattern period */
@@ -531,8 +533,8 @@ void initunits(EN_Project *pr)
pr->Ucf[POWER] = wcf;
pr->Ucf[VOLUME] = hcf * hcf * hcf;
if (time->Hstep < 1800) /* Report time in mins. */
{ /* if hydraulic time step */
pr->Ucf[TIME] = 1.0 / 60.0; /* is less than 1/2 hour. */
{ /* if hydraulic time step */
pr->Ucf[TIME] = 1.0 / 60.0; /* is less than 1/2 hour. */
strcpy(rep->Field[TIME].Units, u_MINUTES);
} else {
pr->Ucf[TIME] = 1.0 / 3600.0;
@@ -606,6 +608,10 @@ void convertunits(EN_Project *pr)
tank->V1max *= tank->Vmax;
}
/* Convert hydraulic convergence criteria */
hyd->FlowChangeLimit /= pr->Ucf[FLOW];
hyd->HeadErrorLimit /= pr->Ucf[HEAD];
/* Convert WQ option concentration units */
qu->Climit /= pr->Ucf[QUALITY];
qu->Ctol /= pr->Ucf[QUALITY];
@@ -678,8 +684,9 @@ void convertunits(EN_Project *pr)
}
////// Moved to inithyd() in hydraul.c ///////
/* Compute flow resistances */
resistance(pr, k);
//resistance(pr, k);
}
/* Convert units on control settings */

View File

@@ -112,7 +112,7 @@ int juncdata(EN_Project *pr)
}
demand->Base = y;
demand->Pat = p;
demand->next = node->D;
demand->next = NULL;
node->D = demand;
hyd->NodeDemand[Njuncs] = y;
@@ -737,6 +737,7 @@ int demanddata(EN_Project *pr)
int j, n, p = 0;
double y;
Pdemand demand;
Pdemand cur_demand;
STmplist *pat;
/* Extract data from tokens */
@@ -778,13 +779,17 @@ int demanddata(EN_Project *pr)
hyd->NodeDemand[j] = MISSING; // marker - next iteration will append a new category.
}
else { // add new demand to junction
cur_demand = net->Node[j].D;
while (cur_demand->next != NULL) {
cur_demand = cur_demand->next;
}
demand = (struct Sdemand *)malloc(sizeof(struct Sdemand));
if (demand == NULL)
return (101);
demand->Base = y;
demand->Pat = p;
demand->next = net->Node[j].D;
net->Node[j].D = demand;
demand->next = NULL;
cur_demand->next = demand;
}
return (0);
} /* end of demanddata */
@@ -1908,6 +1913,10 @@ int optionvalue(EN_Project *pr, int n)
** SPECIFIC GRAVITY value
** TRIALS value
** ACCURACY value
** HEADLIMIT value
** FLOWLIMIT value
** TOLERANCE value
** SEGMENTS value (not used)
** ------ Undocumented Options -----
@@ -1923,18 +1932,20 @@ int optionvalue(EN_Project *pr, int n)
hydraulics_t *hyd = &pr->hydraulics;
quality_t *qu = &pr->quality;
parser_data_t *par = &pr->parser;
char* tok0 = par->Tok[0];
int nvalue = 1; /* Index of token with numerical value */
double y;
/* Check for obsolete SEGMENTS keyword */
if (match(par->Tok[0], w_SEGMENTS))
return (0);
//if (match(par->Tok[0], w_SEGMENTS))
if (match(tok0, w_SEGMENTS))
return (0);
/* Check for missing value (which is permissible) */
if (match(par->Tok[0], w_SPECGRAV) || match(par->Tok[0], w_EMITTER) ||
match(par->Tok[0], w_DEMAND))
if (match(tok0, w_SPECGRAV) || match(tok0, w_EMITTER) ||
match(tok0, w_DEMAND))
nvalue = 2;
if (n < nvalue)
return (0);
@@ -1944,7 +1955,7 @@ int optionvalue(EN_Project *pr, int n)
return (213);
/* Check for WQ tolerance option (which can be 0) */
if (match(par->Tok[0], w_TOLERANCE)) {
if (match(tok0, w_TOLERANCE)) {
if (y < 0.0)
return (213);
qu->Ctol = y; /* Quality tolerance*/
@@ -1952,7 +1963,7 @@ int optionvalue(EN_Project *pr, int n)
}
/* Check for Diffusivity option */
if (match(par->Tok[0], w_DIFFUSIVITY)) {
if (match(tok0, w_DIFFUSIVITY)) {
if (y < 0.0)
return (213);
qu->Diffus = y;
@@ -1960,42 +1971,59 @@ int optionvalue(EN_Project *pr, int n)
}
/* Check for Damping Limit option */
if (match(par->Tok[0], w_DAMPLIMIT)) {
if (match(tok0, w_DAMPLIMIT)) {
hyd->DampLimit = y;
return (0);
}
/* Check for flow change limit*/
else if (match(tok0, w_FLOWCHANGE))
{
if (y < 0.0) return 213;
hyd->FlowChangeLimit = y;
return 0;
}
/* Check for head error limit*/
else if (match(tok0, w_HEADERROR))
{
if (y < 0.0) return 213;
hyd->HeadErrorLimit = y;
return 0;
}
/* All other options must be > 0 */
if (y <= 0.0)
return (213);
/* Assign value to specified option */
if (match(par->Tok[0], w_VISCOSITY))
if (match(tok0, w_VISCOSITY))
hyd->Viscos = y; /* Viscosity */
else if (match(par->Tok[0], w_SPECGRAV))
else if (match(tok0, w_SPECGRAV))
hyd->SpGrav = y; /* Spec. gravity */
else if (match(par->Tok[0], w_TRIALS))
else if (match(tok0, w_TRIALS))
hyd->MaxIter = (int)y; /* Max. trials */
else if (match(par->Tok[0], w_ACCURACY)) /* Accuracy */
else if (match(tok0, w_ACCURACY)) /* Accuracy */
{
y = MAX(y, 1.e-5);
y = MIN(y, 1.e-1);
hyd->Hacc = y;
} else if (match(par->Tok[0], w_HTOL))
}
else if (match(tok0, w_HTOL))
hyd->Htol = y;
else if (match(par->Tok[0], w_QTOL))
else if (match(tok0, w_QTOL))
hyd->Qtol = y;
else if (match(par->Tok[0], w_RQTOL)) {
else if (match(tok0, w_RQTOL)) {
if (y >= 1.0)
return (213);
hyd->RQtol = y;
} else if (match(par->Tok[0], w_CHECKFREQ))
} else if (match(tok0, w_CHECKFREQ))
hyd->CheckFreq = (int)y;
else if (match(par->Tok[0], w_MAXCHECK))
else if (match(tok0, w_MAXCHECK))
hyd->MaxCheck = (int)y;
else if (match(par->Tok[0], w_EMITTER))
else if (match(tok0, w_EMITTER))
hyd->Qexp = 1.0 / y;
else if (match(par->Tok[0], w_DEMAND))
else if (match(tok0, w_DEMAND))
hyd->Dmult = y;
else
return (201);

View File

@@ -70,7 +70,8 @@ int savenetdata(EN_Project *pr)
ibuf[0] = MAGICNUMBER;
/*** CODEVERSION replaces VERSION ***/
ibuf[1] = CODEVERSION;
//ibuf[1] = CODEVERSION;
ibuf[1] = 20012; // keep version at 2.00.12 so that GUI will run
ibuf[2] = net->Nnodes;
ibuf[3] = net->Ntanks;
@@ -251,60 +252,75 @@ int saveenergy(EN_Project *pr)
*/
{
EN_Network *net = &pr->network;
hydraulics_t *hyd = &pr->hydraulics;
out_file_t *out = &pr->out_files;
parser_data_t *par = &pr->parser;
EN_Network *net = &pr->network;
hydraulics_t *hyd = &pr->hydraulics;
out_file_t *out = &pr->out_files;
parser_data_t *par = &pr->parser;
time_options_t *time = &pr->time_options;
FILE *outFile = out->OutFile;
FILE *outFile = out->OutFile;
Spump *pump;
int i, j;
INT4 index;
REAL4 x[6]; /* work array */
double hdur, /* total time->Duration in hours */
t; /* pumping time->Duration */
REAL4 x[MAX_ENERGY_STATS]; // work array
double hdur, // total simulation duration in hours
t; // total pumping time duration
hdur = time->Dur / 3600.0;
for (i = 1; i <= net->Npumps; i++) {
Spump *pump = &net->Pump[i];
pump = &net->Pump[i];
if (hdur == 0.0) {
for (j = 0; j < 5; j++)
x[j] = (REAL4)pump->Energy[j];
x[5] = (REAL4)(pump->Energy[5] * 24.0);
} else {
t = pump->Energy[0];
x[0] = (REAL4)(t / hdur);
x[1] = 0.0f;
x[2] = 0.0f;
x[3] = 0.0f;
x[4] = 0.0f;
if (t > 0.0) {
x[1] = (REAL4)(pump->Energy[1] / t);
x[2] = (REAL4)(pump->Energy[2] / t);
x[3] = (REAL4)(pump->Energy[3] / t);
}
x[4] = (REAL4)pump->Energy[4];
x[5] = (REAL4)(pump->Energy[5] * 24.0 / hdur);
pump->Energy[TOTAL_COST] *= 24.0;
}
x[0] *= 100.0f;
x[1] *= 100.0f;
/* Compute Kw-hr per MilGal (or per cubic meter) */
if (par->Unitsflag == SI)
x[2] *= (REAL4)(1000.0 / LPSperCFS / 3600.0);
else
x[2] *= (REAL4)(1.0e6 / GPMperCFS / 60.0);
for (j = 0; j < 6; j++)
pump->Energy[j] = x[j];
else {
// ... convert total hrs. online to fraction of total time online
t = pump->Energy[PCNT_ONLINE]; //currently holds total hrs. online
pump->Energy[PCNT_ONLINE] = t / hdur;
// ... convert cumulative values to time-averaged ones
if (t > 0.0) {
pump->Energy[PCNT_EFFIC] /= t;
pump->Energy[KWH_PER_FLOW] /= t;
pump->Energy[TOTAL_KWH] /= t;
}
// ... convert total cost to cost per day
pump->Energy[TOTAL_COST] *= 24.0 / hdur;
}
// ... express time online and avg. efficiency as percentages
pump->Energy[PCNT_ONLINE] *= 100.0;
pump->Energy[PCNT_EFFIC] *= 100.0;
// ... compute KWH per Million Gallons or per Cubic Meter
if (par->Unitsflag == SI) {
pump->Energy[KWH_PER_FLOW] *= (1000. / LPSperCFS / 3600.);
}
else {
pump->Energy[KWH_PER_FLOW] *= (1.0e6 / GPMperCFS / 60.);
}
// ... save energy stats to REAL4 work array
for (j = 0; j < MAX_ENERGY_STATS; j++) {
x[j] = (REAL4)pump->Energy[j];
}
// ... save energy results to output file
index = pump->Link;
if (fwrite(&index, sizeof(INT4), 1, outFile) < 1)
if (fwrite(&index, sizeof(INT4), 1, outFile) < 1) {
return (308);
if (fwrite(x, sizeof(REAL4), 6, outFile) < 6)
}
if (fwrite(x, sizeof(REAL4), MAX_ENERGY_STATS, outFile) < MAX_ENERGY_STATS) {
return (308);
}
}
// ... compute and save demand charge
hyd->Emax = hyd->Emax * hyd->Dcost;
x[0] = (REAL4)hyd->Emax;
if (fwrite(&x[0], sizeof(REAL4), 1, outFile) < 1)
if (fwrite(&x[0], sizeof(REAL4), 1, outFile) < 1) {
return (308);
}
return (0);
}

View File

@@ -161,6 +161,9 @@ void initqual(EN_Project *pr)
net->Node[i].S->Smass = 0.0;
}
qu->QTempVolumes =
calloc(net->Ntanks,
sizeof(double)); // keep track of next tank volumes.
qu->QTankVolumes =
calloc(net->Ntanks,
sizeof(double)); // keep track of previous step's tank volumes.
@@ -287,7 +290,7 @@ int nextqual(EN_Project *pr, long *tstep)
{
long hydstep; /* Hydraulic solution time step */
int errcode = 0;
double *tankVolumes;
//double *tankVolumes = NULL;
int i;
EN_Network *net;
hydraulics_t *hyd;
@@ -315,10 +318,10 @@ int nextqual(EN_Project *pr, long *tstep)
// if we're operating in stepwise mode, capture the tank levels so we can
// restore them later.
if (hyd->OpenHflag) {
tankVolumes = calloc(net->Ntanks, sizeof(double));
//tankVolumes = calloc(net->Ntanks, sizeof(double));
for (i = 1; i <= net->Ntanks; ++i) {
if (net->Tank[i].A != 0) { // skip reservoirs
tankVolumes[i - 1] = net->Tank[i].V;
qu->QTempVolumes[i - 1] = net->Tank[i].V;
}
}
@@ -359,7 +362,7 @@ int nextqual(EN_Project *pr, long *tstep)
for (i = 1; i <= net->Ntanks; i++) {
if (net->Tank[i].A != 0) { // skip reservoirs again
int n = net->Tank[i].Node;
net->Tank[i].V = tankVolumes[i - 1];
net->Tank[i].V = qu->QTempVolumes[i - 1];
hyd->NodeHead[n] = tankgrade(pr, i, net->Tank[i].V);
}
}
@@ -370,7 +373,7 @@ int nextqual(EN_Project *pr, long *tstep)
}
}
free(tankVolumes);
//free(tankVolumes);
}
return (errcode);
@@ -448,6 +451,7 @@ int closequal(EN_Project *pr)
free(qu->MassIn);
free(qu->PipeRateCoeff);
free(qu->TempQual);
free(qu->QTempVolumes);
free(qu->QTankVolumes);
free(qu->QLinkFlow);
return (errcode);

View File

@@ -229,6 +229,15 @@ void writesummary(EN_Project *pr)
sprintf(s, FMT27, hyd->Hacc);
writeline(pr, s);
if (hyd->HeadErrorLimit > 0.0) {
sprintf(s, FMT27d, hyd->HeadErrorLimit*pr->Ucf[HEAD], rep->Field[HEAD].Units);
writeline(pr, s);
}
if (hyd->FlowChangeLimit > 0.0) {
sprintf(s, FMT27e, hyd->FlowChangeLimit*pr->Ucf[FLOW], rep->Field[FLOW].Units);
writeline(pr, s);
}
sprintf(s, FMT27a, hyd->CheckFreq);
writeline(pr, s);
sprintf(s, FMT27b, hyd->MaxCheck);
@@ -378,6 +387,7 @@ void writeenergy(EN_Project *pr)
EN_Network *net = &pr->network;
hydraulics_t *hyd = &pr->hydraulics;
report_options_t *rep = &pr->report;
Spump *pump;
int j;
double csum;
@@ -388,14 +398,14 @@ void writeenergy(EN_Project *pr)
writeheader(pr,ENERHDR, 0);
csum = 0.0;
for (j = 1; j <= net->Npumps; j++) {
Spump *pump = &net->Pump[j];
csum += pump->Energy[5];
pump = &net->Pump[j];
csum += pump->Energy[TOTAL_COST];
if (rep->LineNum == (long)rep->PageSize)
writeheader(pr, ENERHDR, 1);
sprintf(s, "%-8s %6.2f %6.2f %9.2f %9.2f %9.2f %9.2f",
net->Link[pump->Link].ID, pump->Energy[0], pump->Energy[1],
pump->Energy[2], pump->Energy[3], pump->Energy[4],
pump->Energy[5]);
net->Link[pump->Link].ID, pump->Energy[PCNT_ONLINE], pump->Energy[PCNT_EFFIC],
pump->Energy[KWH_PER_FLOW], pump->Energy[TOTAL_KWH], pump->Energy[MAX_KW],
pump->Energy[TOTAL_COST]);
writeline(pr, s);
}
fillstr(s, '-', 63);

View File

@@ -140,7 +140,10 @@ AUTHOR: L. Rossman
#define w_RQTOL "RQTOL"
#define w_CHECKFREQ "CHECKFREQ"
#define w_MAXCHECK "MAXCHECK"
#define w_DAMPLIMIT "DAMPLIMIT"
#define w_DAMPLIMIT "DAMPLIMIT"
#define w_FLOWCHANGE "FLOWCHANGE"
#define w_HEADERROR "HEADERROR"
#define w_SECONDS "SEC"
#define w_MINUTES "MIN"
@@ -364,7 +367,10 @@ AUTHOR: L. Rossman
#define FMT27a " Status Check Frequency ............ %-d"
#define FMT27b " Maximum Trials Checked ............ %-d"
#define FMT27c " Damping Limit Threshold ........... %-.6f"
#define FMT27c " Damping Limit Threshold ........... %-.6f"
#define FMT27d " Headloss Error Limit .............. %-.6f %s"
#define FMT27e " Flow Change Limit ................. %-.6f %s"
#define FMT28 " Maximum Trials .................... %-d"
#define FMT29 " Quality Analysis .................. None"
@@ -409,10 +415,13 @@ AUTHOR: L. Rossman
#define FMT61 "%10s: Valve %s caused ill-conditioning"
#define FMT62 "%10s: System ill-conditioned at node %s"
#define FMT63 "%10s: %s %s changed by rule %s"
#define FMT64 "%10s: Balancing the network:"
#define FMT64 "%10s: Balancing the network:\n"
#define FMT65 " Trial %2d: relative flow change = %-.6f"
/*** End of update ***/
#define FMT66 " maximum flow change = %.4f for Link %s"
#define FMT67 " maximum head error = %.4f for Link %s\n"
/* -------------------- Energy Report Table ------------------- */
#define FMT71 "Energy Usage:"
#define FMT72 \

View File

@@ -47,7 +47,7 @@ typedef int INT4;
#define EOFMARK 0x1A /* Use 0x04 for UNIX systems */
#define MAXTITLE 3 /* Max. # title lines */
#define MAXID 31 /* Max. # characters in ID name */
#define MAXMSG 79 /* Max. # characters in message text */
#define MAXMSG 79 /* Max. # characters in message text */
#define MAXLINE 255 /* Max. # characters read from input line */
#define MAXFNAME 259 /* Max. # characters in file name */
#define MAXTOKS 40 /* Max. items per line of input */
@@ -59,6 +59,9 @@ typedef int INT4;
#define TINY 1.E-6
#define MISSING -1.E10
#define CBIG 1.e8 /* Big coefficient */
#define CSMALL 1.e-6 /* Small coefficient */
#ifdef M_PI
#define PI M_PI
#else
@@ -135,21 +138,21 @@ typedef enum {
USE, /* use from previous run */
SAVE, /* save after current run */
SCRATCH
} Hydtype; /* use temporary file */
} Hydtype; /* use temporary file */
typedef enum {
NONE, /* no quality analysis */
CHEM, /* analyze a chemical */
AGE, /* analyze water age */
TRACE
} QualType; /* trace % of flow from a source */
} QualType; /* trace % of flow from a source */
typedef enum {
V_CURVE, /* volume curve */
P_CURVE, /* pump curve */
E_CURVE, /* efficiency curve */
V_CURVE, /* volume curve */
P_CURVE, /* pump curve */
E_CURVE, /* efficiency curve */
H_CURVE
} CurveType; /* head loss curve */
} CurveType; /* head loss curve */
typedef enum {
CONST_HP, /* constant horsepower */
@@ -169,8 +172,8 @@ typedef enum {
LOWLEVEL, /* act when grade below set level */
HILEVEL, /* act when grade above set level */
TIMER, /* act when set time reached */
TIMEOFDAY
} ControlType; /* act when time of day occurs */
TIMEOFDAY /* act when time of day occurs */
} ControlType;
typedef enum {
XHEAD, /* pump cannot deliver head (closed) */
@@ -183,18 +186,18 @@ typedef enum {
XPRESSURE, /* valve cannot supply pressure */
FILLING, /* tank filling */
EMPTYING
} StatType; /* tank emptying */
} StatType; /* tank emptying */
typedef enum {
HW, /* Hazen-Williams */
DW, /* Darcy-Weisbach */
CM
} FormType; /* Chezy-Manning */
CM /* Chezy-Manning */
} FormType;
typedef enum {
US, /* US */
SI
} UnitsType; /* SI (metric) */
SI /* SI (metric) */
} UnitsType;
typedef enum {
CFS, /* cubic feet per second */
@@ -206,40 +209,41 @@ typedef enum {
LPM, /* liters per minute */
MLD, /* megaliters per day */
CMH, /* cubic meters per hour */
CMD
} FlowUnitsType; /* cubic meters per day */
CMD /* cubic meters per day */
} FlowUnitsType;
typedef enum {
PSI, /* pounds per square inch */
KPA, /* kiloPascals */
METERS
} PressUnitsType; /* meters */
METERS /* meters */
} PressUnitsType;
typedef enum {
LOW, /* lower limit */
HI, /* upper limit */
PREC
} RangeType; /* precision */
PREC /* precision */
} RangeType;
typedef enum {
MIX1, /* 1-compartment model */
MIX2, /* 2-compartment model */
FIFO, /* First in, first out model */
LIFO
} MixType; /* Last in, first out model */
LIFO /* Last in, first out model */
} MixType;
typedef enum {
SERIES, /* none */
AVG, /* time-averages */
MIN, /* minimum values */
MAX, /* maximum values */
RANGE
} TstatType; /* max - min values */
RANGE /* max - min values */
} TstatType;
#define MAXVAR 21 /* Max. # types of network variables */
/* (equals # items enumed below) */
#define MAXVAR 21 /* Max. # types of network variables */
/* (equals # items enumed below) */
typedef enum {
ELEV = 0, /* nodal elevation */
ELEV = 0, /* nodal elevation */
DEMAND, /* nodal demand flow */
HEAD, /* nodal hydraulic head */
PRESSURE, /* nodal pressure */
@@ -273,17 +277,27 @@ typedef enum {
} SectType;
typedef enum {
STATHDR, /* Hydraulic Status */
ENERHDR, /* Energy Usage */
NODEHDR, /* Node Results */
LINKHDR
} HdrType; /* Link Results */
STATHDR, /* Hydraulic Status header */
ENERHDR, /* Energy Usage header */
NODEHDR, /* Node Results header */
LINKHDR /* Link Results header */
} HdrType;
typedef enum {
POSITIVE,
NEGATIVE
} FlowDirection;
typedef enum {
PCNT_ONLINE,
PCNT_EFFIC,
KWH_PER_FLOW,
TOTAL_KWH,
MAX_KW,
TOTAL_COST,
MAX_ENERGY_STATS
} EnergyStats;
/*
------------------------------------------------------
Global Data Structures
@@ -344,6 +358,16 @@ struct Sdemand /* DEMAND CATEGORY OBJECT */
};
typedef struct Sdemand *Pdemand; /* Pointer to demand object */
typedef struct
{
double hrsOnLine; // hours pump is online
double efficiency; // total time wtd. efficiency
double kwHrsPerCFS; // total kw-hrs per cfs of flow
double kwHrs; // total kw-hrs consumed
double maxKwatts; // max. kw consumed
double totalCost; // total pumping cost
} Senergy;
struct Ssource /* WQ SOURCE OBJECT */
{
/*int Node;*/ /* Node index of source */
@@ -422,13 +446,7 @@ typedef struct /* PUMP OBJECT */
int Upat; /* Utilization pattern index */
int Epat; /* Energy cost pattern index */
double Ecost; /* Unit energy cost */
double Energy[6]; /* Energy usage statistics: */
/* 0 = pump utilization */
/* 1 = avg. efficiency */
/* 2 = avg. kW/flow */
/* 3 = avg. kwatts */
/* 4 = peak kwatts */
/* 5 = cost/day */
double Energy[MAX_ENERGY_STATS]; /* Energy usage statistics */
} Spump;
typedef struct /* VALVE OBJECT */
@@ -474,7 +492,7 @@ typedef struct /* FIELD OBJECT of report table */
double RptLim[2]; /* Lower/upper report limits */
} SField;
typedef struct s_Premise /* Rule Premise Clause */
typedef struct s_Premise /* Rule Premise Clause */
{
int logop; /* Logical operator */
int object; /* Node or link */
@@ -486,7 +504,7 @@ typedef struct s_Premise /* Rule Premise Clause */
struct s_Premise *next;
} Premise;
typedef struct s_Action /* Rule Action Clause */
typedef struct s_Action /* Rule Action Clause */
{
int link; /* Link index */
int status; /* Link's status */
@@ -494,19 +512,19 @@ typedef struct s_Action /* Rule Action Clause */
struct s_Action *next;
} Action;
typedef struct s_aRule /* Control Rule Structure */
typedef struct s_aRule /* Control Rule Structure */
{
char label[MAXID+1]; /* Rule character label */
double priority; /* Priority level */
Premise *Pchain; /* Linked list of premises */
Action *Tchain; /* Linked list of actions if true */
Action *Fchain; /* Linked list of actions if false */
char label[MAXID+1]; /* Rule character label */
double priority; /* Priority level */
Premise *Pchain; /* Linked list of premises */
Action *Tchain; /* Linked list of actions if true */
Action *Fchain; /* Linked list of actions if false */
struct s_aRule *next;
} aRule;
typedef struct s_ActItem /* Action list item */
typedef struct s_ActItem /* Action list item */
{
int ruleindex; /* Index of rule action belongs to */
int ruleindex; /* Index of rule action belongs to */
struct s_Action *action; /* An action structure */
struct s_ActItem *next;
} ActItem;
@@ -542,6 +560,7 @@ typedef struct {
Climit, /// Limiting potential quality
*NodeQual, /// Node quality state
*TempQual, /// General purpose array for water quality
*QTempVolumes,
*QTankVolumes,
*QLinkFlow,
*PipeRateCoeff;
@@ -551,12 +570,12 @@ typedef struct {
Qtime; /// Current quality time (sec)
char OutOfMemory; /* Out of memory indicator */
alloc_handle_t *SegPool; // Memory pool for water quality segments
alloc_handle_t *SegPool; // Memory pool for water quality segments
Pseg FreeSeg; /* Pointer to unused segment */
Pseg *FirstSeg, /* First (downstream) segment in each pipe */
*LastSeg; /* Last (upstream) segment in each pipe */
FlowDirection *FlowDir; /* Flow direction for each pipe */
*LastSeg; /* Last (upstream) segment in each pipe */
FlowDirection *FlowDir; /* Flow direction for each pipe */
double *VolIn; /* Total volume inflow to node */
double *MassIn; /* Total mass inflow to node */
double Sc; /* Schmidt Number */
@@ -613,15 +632,15 @@ typedef struct {
*Patlist, /* Temporary time pattern list */
*Curvelist; /* Temporary list of curves */
double *X; // temporary array for curve data
double *X; // temporary array for curve data
int
Ntokens, /* Number of tokens in input line */
Ntitle; /* Number of title lines */
Ntokens, /* Number of tokens in input line */
Ntitle; /* Number of title lines */
char *Tok[MAXTOKS]; /* Array of token strings */
char *Tok[MAXTOKS]; /* Array of token strings */
char Comment[MAXMSG+1];
STmplist *PrevPat; /* Pointer to pattern list element */
STmplist *PrevCurve; /* Pointer to curve list element */
STmplist *PrevPat; /* Pointer to pattern list element */
STmplist *PrevCurve; /* Pointer to curve list element */
} parser_data_t;
@@ -646,7 +665,7 @@ typedef struct {
Rpt1Fname[MAXFNAME+1], /* Primary report file name */
Rpt2Fname[MAXFNAME+1]; /* Secondary report file name */
SField Field[MAXVAR]; /* Output reporting fields */
SField Field[MAXVAR]; /* Output reporting fields */
long LineNum; /* Current line number */
long PageNum; /* Current page number */
@@ -693,12 +712,11 @@ typedef struct {
aRule *Rule; /* Array of rules */
ActItem *ActList; /* Linked list of action items */
int RuleState; /* State of rule interpreter */
long Time1; /* Start of rule evaluation time interval (sec) */
int RuleState; /* State of rule interpreter */
long Time1; /* Start of rule evaluation time interval (sec) */
Premise *Plast; /* Previous premise clause */
Action *Tlast; /* Previous true action */
Action *Flast; /* Previous false action */
} rules_t;
/*
@@ -753,6 +771,10 @@ typedef struct {
Qexp, /* Exponent in orifice formula */
Dmult, /* Demand multiplier */
Hacc, /* Hydraulics solution accuracy */
FlowChangeLimit, /* Hydraulics flow change limit */
HeadErrorLimit, /* Hydraulics head error limit */
DampLimit, /* Solution damping threshold */
Viscos, /* Kin. viscosity (sq ft/sec) */
SpGrav, /* Specific gravity */
@@ -796,7 +818,7 @@ typedef struct {
} hydraulics_t;
typedef struct {
int Nnodes, /* Number of network nodes */
int Nnodes, /* Number of network nodes */
Ntanks, /* Number of tanks */
Njuncs, /* Number of junction nodes */
Nlinks, /* Number of network links */
@@ -809,17 +831,18 @@ typedef struct {
Ncurves, /* Number of data curves */
Ncoords; /* Number of Coords */
Snode *Node; /* Node data */
Slink *Link; /* Link data */
Stank *Tank; /* Tank data */
Spump *Pump; /* Pump data */
Svalve *Valve; /* Valve data */
Spattern *Pattern; /* Time patterns */
Scurve *Curve; /* Curve data */
Scoord *Coord; /* Coordinate data */
Scontrol *Control; /* Control data */
ENHashTable *NodeHashTable, *LinkHashTable; /* Hash tables for ID labels */
Padjlist *Adjlist; /* Node adjacency lists */
Snode *Node; /* Node data */
Slink *Link; /* Link data */
Stank *Tank; /* Tank data */
Spump *Pump; /* Pump data */
Svalve *Valve; /* Valve data */
Spattern *Pattern; /* Time patterns */
Scurve *Curve; /* Curve data */
Scoord *Coord; /* Coordinate data */
Scontrol *Control; /* Control data */
ENHashTable *NodeHashTable,
*LinkHashTable; /* Hash tables for ID labels */
Padjlist *Adjlist; /* Node adjacency lists */
} EN_Network;
@@ -851,5 +874,4 @@ typedef struct EN_Project {
} EN_Project;
#endif