Merge branch 'dev' into Update-ReleaseNotes2_2.md

This commit is contained in:
Elad Salomons
2018-10-29 05:58:55 +02:00
committed by GitHub
12 changed files with 335 additions and 253 deletions

View File

@@ -1,4 +1,3 @@
Release Notes for EPANET 2.2 (Draft)
============================
@@ -29,7 +28,7 @@ int runEpanet(char *finp, char *frpt)
if (!err) err = EN_solveH(ph);
if (!err) err = EN_report(ph);
EN_close(ph);
EN_deleteproject(ph);
EN_deleteproject(&ph);
return err;
}
```

View File

@@ -288,7 +288,8 @@ Public Const EN_G_CURVE = 4 ' General\default curve
Declare Function ENinit Lib "epanet2.dll" (ByVal rptFile As String, ByVal binOutFile As String, ByVal UnitsType As Long, ByVal HeadlossFormula As Long) As Long
Declare Function ENsetheadcurveindex Lib "epanet2.dll" (ByVal pumpIndex As Long, ByVal curveIndex As Long) As Long
Declare Function ENsetlinktype Lib "epanet2.dll" (ByVal index As Long, ByVal code As Long) As Long
Declare Function ENsetlinknodes Lib "epanet2.dll" (ByVal index As Long, ByVal node1 As Long, ByVal node2 As Long) As Long
Declare Function ENsetlinktype Lib "epanet2.dll" (index As Long, ByVal code As Long) As Long
Declare Function ENaddnode Lib "epanet2.dll" (ByVal id As String, ByVal nodeType As Long) As Long
Declare Function ENaddlink Lib "epanet2.dll" (ByVal id As String, ByVal linkType As Long, ByVal fromNode As String, ByVal toNode As String) As Long
Declare Function ENdeletelink Lib "epanet2.dll" (ByVal nodeIndex As Long) As Long

View File

@@ -67,6 +67,9 @@
// --- Define the EPANET toolkit constants
#define EN_MAXID 31 /**< Max. # characters in ID name */
#define EN_MAXMSG 255 /**< Max. # characters in message text */
/// Node property codes
typedef enum {
EN_ELEVATION = 0, /**< Node Elevation */
@@ -740,12 +743,12 @@ extern "C" {
/**
@brief Set the link type code for a specified link
@param id The id of a link
@param type The type code of the link.
@param[in,out] index The index of a link before [in] and after [out] the type change.
@param code The new type code of the link.
@return Error code
@see EN_LinkType
*/
int DLLEXPORT ENsetlinktype(char *id, EN_LinkType type);
int DLLEXPORT ENsetlinktype(int *index, EN_LinkType code);
/**
@brief Get the indexes of a link's start- and end-nodes.
@@ -869,6 +872,16 @@ extern "C" {
*/
int DLLEXPORT ENsetlinkid(int index, char *newid);
/**
@brief Set the indexes of a link's start- and end-nodes.
@param index The index of a link (first link is index 1)
@param node1 The index of the link's start node (first node is index 1).
@param node2 The index of the link's end node (first node is index 1).
@return Error code
@see ENsetnodeid, ENsetlinkid
*/
int DLLEXPORT ENsetlinknodes(int index, int node1, int node2);
/**
@brief Set a property value for a link.
@param index The index of a link. First link is index 1.
@@ -1061,7 +1074,6 @@ extern "C" {
@see ENgetcurveindex ENsetcurve
*/
int DLLEXPORT ENaddcurve(char *id);
/**
@brief Gets the number of premises, true actions, and false actions and the priority of an existing rule-based control.
@@ -1300,7 +1312,6 @@ extern "C" {
int DLLEXPORT EN_getlinkindex(EN_ProjectHandle ph, char *id, int *index);
int DLLEXPORT EN_getlinkid(EN_ProjectHandle ph, int index, char *id);
int DLLEXPORT EN_getlinktype(EN_ProjectHandle ph, int index, EN_LinkType *code);
int DLLEXPORT EN_setlinktype(EN_ProjectHandle ph, char *id, EN_LinkType type);
int DLLEXPORT EN_getlinknodes(EN_ProjectHandle ph, int index, int *node1, int *node2);
int DLLEXPORT EN_getlinkvalue(EN_ProjectHandle ph, int index, EN_LinkProperty code, EN_API_FLOAT_TYPE *value);
int DLLEXPORT EN_getcurve(EN_ProjectHandle ph, int curveIndex, char* id, int *nValues, EN_API_FLOAT_TYPE **xValues, EN_API_FLOAT_TYPE **yValues);
@@ -1316,6 +1327,8 @@ extern "C" {
int DLLEXPORT EN_setnodeid(EN_ProjectHandle ph, int index, char *newid);
int DLLEXPORT EN_setnodevalue(EN_ProjectHandle ph, int index, int code, EN_API_FLOAT_TYPE v);
int DLLEXPORT EN_setlinkid(EN_ProjectHandle ph, int index, char *newid);
int DLLEXPORT EN_setlinknodes(EN_ProjectHandle ph, int index, int node1, int node2);
int DLLEXPORT EN_setlinktype(EN_ProjectHandle ph, int *index, EN_LinkType code);
int DLLEXPORT EN_setlinkvalue(EN_ProjectHandle ph, int index, int code, EN_API_FLOAT_TYPE v);
int DLLEXPORT EN_addpattern(EN_ProjectHandle ph, char *id);
int DLLEXPORT EN_setpattern(EN_ProjectHandle ph, int index, EN_API_FLOAT_TYPE *f, int len);

View File

@@ -230,6 +230,8 @@ Public Const EN_CUSTOM = 2 ' user-defined custom curve
Declare Function ENsetnodeid Lib "epanet2.dll" (ByVal index As Int32, ByVal newid As String) As Int32
Declare Function ENsetnodevalue Lib "epanet2.dll" (ByVal Index As Int32, ByVal Code As Int32, ByVal Value As Single) As Int32
Declare Function ENsetlinkid Lib "epanet2.dll" (ByVal index As Int32, ByVal newid As String) As Int32
Declare Function ENsetlinknodes Lib "epanet2.dll" (ByVal index As Int32, ByVal node1 As Int32, ByVal node2 As Int32) As Int32
Declare Function ENsetlinktype Lib "epanet2.dll" (ByRef index As Int32, ByVal code As Int32) As Int32
Declare Function ENsetlinkvalue Lib "epanet2.dll" (ByVal Index As Int32, ByVal Code As Int32, ByVal Value As Single) As Int32
Declare Function ENsetpattern Lib "epanet2.dll" (ByVal Index as Int32, ByRef F as Single, ByVal N as Int32) as Int32
Declare Function ENsetpatternvalue Lib "epanet2.dll" (ByVal Index As Int32, ByVal Period As Int32, ByVal Value As Single) As Int32

View File

@@ -144,43 +144,6 @@ void errorLookup(int errcode, char *errmsg, int len);
*****************************************************************/
int runconcurrent(EN_ProjectHandle ph, const char *inputfile, const char *reportfile,
const char *outputfile, void(*pviewprog)(char *))
{
long t, tstep_h, tstep_q;
int errcode = 0;
EN_Project *p = NULL;
ERRCODE(EN_open(ph, inputfile, reportfile, outputfile));
p = (EN_Project*)(ph);
p->viewprog = pviewprog;
ERRCODE(EN_openH(ph));
ERRCODE(EN_initH(ph, EN_SAVE));
ERRCODE(EN_openQ(ph));
ERRCODE(EN_initQ(ph, EN_SAVE));
do {
ERRCODE(EN_runH(ph, &t));
ERRCODE(EN_runQ(ph, &t));
ERRCODE(EN_nextH(ph, &tstep_h));
ERRCODE(EN_nextQ(ph, &tstep_q));
} while (tstep_h > 0);
ERRCODE(EN_closeH(ph));
ERRCODE(EN_closeQ(ph));
ERRCODE(EN_report(ph));
ERRCODE(EN_close(ph));
return errcode;
}
/*------------------------------------------------------------------------
** Input: f1 = pointer to name of input file
** f2 = pointer to name of report file
@@ -201,14 +164,17 @@ int runconcurrent(EN_ProjectHandle ph, const char *inputfile, const char *report
int DLLEXPORT ENepanet(const char *f1, const char *f2, const char *f3, void (*pviewprog)(char *))
{
int errcode = 0;
int warncode = 0;
EN_Project *p = NULL;
ERRCODE(EN_createproject(&_defaultModel));
ERRCODE(EN_runproject(_defaultModel, f1, f2, f3, pviewprog));
if (errcode < 100) warncode = errcode;
ERRCODE(EN_deleteproject(&_defaultModel));
if (warncode) errcode = MAX(errcode, warncode);
return (errcode);
}
@@ -449,6 +415,14 @@ int DLLEXPORT ENsetlinkid(int index, char *newid) {
return EN_setlinkid(_defaultModel, index, newid);
}
int DLLEXPORT ENsetlinknodes(int index, int node1, int node2) {
return EN_setlinknodes(_defaultModel, index, node1, node2);
}
int DLLEXPORT ENsetlinktype(int *index, EN_LinkType type) {
return EN_setlinktype(_defaultModel, index, type);
}
int DLLEXPORT ENsetlinkvalue(int index, int code, EN_API_FLOAT_TYPE v) {
return EN_setlinkvalue(_defaultModel, index, code, v);
}
@@ -601,10 +575,6 @@ int DLLEXPORT ENgetruleID(int indexRule, char* id){
return EN_getruleID(_defaultModel, indexRule, 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);
}
@@ -682,7 +652,8 @@ int DLLEXPORT EN_runproject(EN_ProjectHandle ph, const char *f1, const char *f2,
ERRCODE(EN_report(ph));
EN_close(ph);
if (p->Warnflag) errcode = MAX(errcode, p->Warnflag);
return errcode;
}
@@ -792,7 +763,6 @@ int DLLEXPORT EN_open(EN_ProjectHandle ph, const char *f1, const char *f2, const
writelogo(p);
/* Find network size & allocate memory for data */
writecon(FMT02);
writewin(p->viewprog, FMT100);
ERRCODE(netsize(p));
ERRCODE(allocdata(p));
@@ -920,19 +890,14 @@ int DLLEXPORT EN_solveH(EN_ProjectHandle ph)
if (!errcode) {
/* Initialize hydraulics */
errcode = EN_initH(ph, EN_SAVE);
writecon(FMT14);
/* Analyze each hydraulic period */
if (!errcode)
do {
/* Display progress message */
/*** Updated 6/24/02 ***/
sprintf(p->Msg, "%-10s",
clocktime(p->report.Atime, p->time_options.Htime));
writecon(p->Msg);
sprintf(p->Msg, FMT101, p->report.Atime);
writewin(p->viewprog, p->Msg);
@@ -940,16 +905,10 @@ 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);
}
/* Close hydraulics solver */
/*** Updated 6/24/02 ***/
writecon("\b\b\b\b\b\b\b\b ");
EN_closeH(ph);
errcode = MAX(errcode, p->Warnflag);
@@ -1190,24 +1149,15 @@ int DLLEXPORT EN_solveQ(EN_ProjectHandle ph) {
if (!errcode) {
/* Initialize WQ */
errcode = EN_initQ(ph, EN_SAVE);
if (p->quality.Qualflag)
writecon(FMT15);
else {
writecon(FMT16);
writewin(p->viewprog, FMT103);
}
if (!p->quality.Qualflag) writewin(p->viewprog, FMT106);
/* Analyze each hydraulic period */
if (!errcode)
do {
/* Display progress message */
/*** Updated 6/24/02 ***/
sprintf(p->Msg, "%-10s",
clocktime(p->report.Atime, p->time_options.Htime));
writecon(p->Msg);
if (p->quality.Qualflag) {
sprintf(p->Msg, FMT102, p->report.Atime);
writewin(p->viewprog, p->Msg);
@@ -1217,17 +1167,10 @@ int DLLEXPORT EN_solveQ(EN_ProjectHandle ph) {
tstep = 0;
ERRCODE(EN_runQ(ph, &t));
ERRCODE(EN_nextQ(ph, &tstep));
/*** Updated 6/24/02 ***/
writecon("\b\b\b\b\b\b\b\b\b\b");
} while (tstep > 0);
}
/* Close WQ solver */
/*** Updated 6/24/02 ***/
writecon("\b\b\b\b\b\b\b\b ");
EN_closeQ(ph);
return set_error(p->error_handle, errcode);
}
@@ -1355,6 +1298,7 @@ int DLLEXPORT EN_report(EN_ProjectHandle ph) {
/* Check if results saved to binary output file */
if (!p->save_options.SaveQflag)
return set_error(p->error_handle, 106);
writewin(p->viewprog, FMT103);
errcode = writereport(p);
if (errcode)
errmsg(p, errcode);
@@ -3220,6 +3164,37 @@ int DLLEXPORT EN_setlinkid(EN_ProjectHandle ph, int index, char *newid)
return set_error(p->error_handle, 0);
}
int DLLEXPORT EN_setlinknodes(EN_ProjectHandle ph, int index, int node1, int node2)
{
int type;
EN_Project *p = (EN_Project*)ph;
EN_Network *net = &p->network;
// Check that nodes exist
if (node1 < 0 || node1 > net->Nnodes) return set_error(p->error_handle, 203);
if (node2 < 0 || node2 > net->Nnodes) return set_error(p->error_handle, 203);
// Check for illegal valve connection
type = net->Link[index].Type;
if (type == EN_PRV || type == EN_PSV || type == EN_FCV)
{
// Can't be connected to a fixed grade node
if (node1 > net->Njuncs ||
node2 > net->Njuncs) return set_error(p->error_handle, 219);
// Can't be connected to another pressure/flow control valve
if (!valvecheck(p, type, node1, node2))
{
return set_error(p->error_handle, 220);
}
}
// Assign new end nodes to link
net->Link[index].N1 = node1;
net->Link[index].N2 = node2;
return set_error(p->error_handle, 0);
}
int DLLEXPORT EN_setlinkvalue(EN_ProjectHandle ph, int index, int code,
EN_API_FLOAT_TYPE v)
@@ -3835,6 +3810,7 @@ int DLLEXPORT EN_setoption(EN_ProjectHandle ph, int code, EN_API_FLOAT_TYPE v)
for (demand = node->D; demand != NULL; demand = demand->next) {
if (demand->Pat == tmpPat) {
demand->Pat = (int)value;
strcpy(demand->Name, "");
}
}
}
@@ -3973,7 +3949,7 @@ int DLLEXPORT EN_setheadcurveindex(EN_ProjectHandle ph, int index, int curveinde
pump->Ptype = NOCURVE;
pump->Hcurve = curveindex;
// update pump parameters
getpumpparams(p);
updatepumpparams(p, pIdx);
// convert units
if (pump->Ptype == POWER_FUNC) {
pump->H0 /= Ucf[HEAD];
@@ -4063,20 +4039,16 @@ int openfiles(EN_Project *p, const char *f1, const char *f2, const char *f3)
/* Check that file names are not identical */
if (strcomp(f1, f2) || strcomp(f1, f3) ||
(strcomp(f2, f3) && (strlen(f2) > 0 || strlen(f3) > 0))) {
writecon(FMT04);
return 301;
}
/* Attempt to open input and report files */
if ((par->InFile = fopen(f1, "rt")) == NULL) {
writecon(FMT05);
writecon(f1);
return 302;
}
if (strlen(f2) == 0)
rep->RptFile = stdout;
else if ((rep->RptFile = fopen(f2, "wt")) == NULL) {
writecon(FMT06);
return 303;
}
@@ -4207,7 +4179,6 @@ int openoutfile(EN_Project *p)
if (out->Outflag == SAVE)
{
if ((out->OutFile = fopen(out->OutFname, "w+b")) == NULL) {
writecon(FMT07);
errcode = 304;
}
}
@@ -4217,7 +4188,6 @@ int openoutfile(EN_Project *p)
getTmpName(p, out->OutFname);
if ((out->OutFile = fopen(out->OutFname, "w+b")) == NULL)
{
writecon(FMT08);
errcode = 304;
}
}
@@ -4714,6 +4684,7 @@ char *geterrmsg(int errcode, char *msg)
{
switch (errcode) { /* Warnings */
#define DAT(code,enumer,string) case code: strcpy(msg, string); break;
//#define DAT(code,enumer,string) case code: sprintf(msg, "Error %d: %s", code, string); break;
#include "errors.dat"
#undef DAT
default:
@@ -4732,26 +4703,12 @@ void errmsg(EN_Project *p, int errcode)
{
if (errcode == 309) /* Report file write error - */
{ /* Do not write msg to file. */
writecon("\n ");
writecon(geterrmsg(errcode,p->Msg));
} else if (p->report.RptFile != NULL && p->report.Messageflag) {
writeline(p, geterrmsg(errcode,p->Msg));
}
}
void writecon(const char *s)
/*----------------------------------------------------------------
** Input: text string
** Output: none
** Purpose: writes string of characters to console
**----------------------------------------------------------------
*/
{
fprintf(stdout, "%s", s);
fflush(stdout);
}
void writewin(void (*vp)(char *), char *s)
/*----------------------------------------------------------------
** Input: text string
@@ -4871,8 +4828,6 @@ int DLLEXPORT EN_setdemandname(EN_ProjectHandle ph, int nodeIndex, int demandIdx
const int Nnodes = net->Nnodes;
const int Njuncs = net->Njuncs;
double *Ucf = pr->Ucf;
Pdemand d;
int n = 1;
/* Check for valid arguments */
@@ -4889,7 +4844,7 @@ int DLLEXPORT EN_setdemandname(EN_ProjectHandle ph, int nodeIndex, int demandIdx
}
int DLLEXPORT EN_setdemandpattern(EN_ProjectHandle ph, int nodeIndex, int demandIdx, int patIndex) {
EN_Project *pr = (EN_Project*)ph;
EN_Network *net = &pr->network;
@@ -4964,43 +4919,50 @@ int DLLEXPORT EN_getaveragepatternvalue(EN_ProjectHandle ph, int index, EN_API_F
return set_error(p->error_handle, 0);
}
int DLLEXPORT EN_setlinktype(EN_ProjectHandle ph, char *id, EN_LinkType toType) {
int i;
EN_LinkType fromType;
EN_Project *p = (EN_Project*)ph;
int DLLEXPORT EN_setlinktype(EN_ProjectHandle ph, int *index, EN_LinkType type) {
EN_Network *net = &p->network;
int i = *index, n1, n2;
char id[MAXID+1];
char id1[MAXID+1];
char id2[MAXID+1];
int errcode;
EN_LinkType oldtype;
EN_Project *p = (EN_Project*)ph;
EN_Network *net = &p->network;
if (!p->Openflag)
return set_error(p->error_handle, 102);
if (!p->Openflag) return set_error(p->error_handle, 102);
if (type < 0 || type > EN_GPV) return set_error(p->error_handle, 211);
/* Check if a link with the id exists */
if (EN_getlinkindex(p, id, &i) != 0)
return set_error(p->error_handle, 215);
// Check if a link with the id exists
if (i <= 0 || i > net->Nlinks) return set_error(p->error_handle, 204);
/* Get the current type of the link */
EN_getlinktype(p, i, &fromType);
if (fromType == toType)
return set_error(p->error_handle, 0);
// Get the current type of the link
EN_getlinktype(p, i, &oldtype);
if (oldtype == type) return set_error(p->error_handle, 0);
/* Change link from Pipe */
if (toType <= EN_PIPE) {
net->Npipes++;
} else if (toType == EN_PUMP) {
net->Npumps++;
net->Pump[net->Npumps].Link = i;
} else {
net->Nvalves++;
net->Valve[net->Nvalves].Link = i;
}
// Pipe changing from or to having a check valve
if (oldtype <= EN_PIPE && type <= EN_PIPE)
{
net->Link[i].Type = type;
if (type == EN_CVPIPE) net->Link[i].Stat = OPEN;
return set_error(p->error_handle, 0);
}
if (fromType <= EN_PIPE) {
net->Npipes--;
} else if (fromType == EN_PUMP) {
net->Npumps--;
}
return set_error(p->error_handle, 0);
// Get ID's of link & its end nodes
EN_getlinkid(ph, i, id);
EN_getlinknodes(ph, i, &n1, &n2);
EN_getnodeid(ph, n1, id1);
EN_getnodeid(ph, n2, id2);
// Delete the original link
EN_deletelink(ph, i);
// Create a new link of new type and old id
errcode = EN_addlink(ph, id, type, id1, id2);
// Find the index of this new link
EN_getlinkindex(ph, id, index);
return set_error(p->error_handle, errcode);
}
int DLLEXPORT EN_addnode(EN_ProjectHandle ph, char *id, EN_NodeType nodeType) {
@@ -5047,6 +5009,7 @@ int DLLEXPORT EN_addnode(EN_ProjectHandle ph, char *id, EN_NodeType nodeType) {
demand = (struct Sdemand *)malloc(sizeof(struct Sdemand));
demand->Base = 0.0;
demand->Pat = hyd->DefPat; // Use default pattern
strcpy(demand->Name, "");
demand->next = NULL;
node->D = demand;

View File

@@ -52,7 +52,6 @@ int findvalve(EN_Network *n, int); /* Find valve index from node
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 --------------------*/
@@ -75,6 +74,7 @@ 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 updatepumpparams(EN_Project *pr, int); // Updates 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 */

View File

@@ -356,6 +356,7 @@ void adjustdata(EN_Project *pr)
for (demand = node->D; demand != NULL; demand = demand->next) {
if (demand->Pat == 0) {
demand->Pat = hyd->DefPat;
strcpy(demand->Name, "");
}
}
}

View File

@@ -40,10 +40,10 @@ The following utility functions are all called from INPUT3.C
#define MAXERRS 10 /* Max. input errors reported */
/* Defined in enumstxt.h in EPANET.C */
extern char *SectTxt[]; /* Input section keywords */
int netsize(EN_Project *pr)
/*
**--------------------------------------------------------------
@@ -206,9 +206,10 @@ int readdata(EN_Project *pr)
/* Check if max. length exceeded */
if (strlen(line) >= MAXLINE) {
char errMsg[MAXMSG+1];
EN_geterror(214, errMsg, MAXMSG);
sprintf(pr->Msg, "%s section: %s", errMsg, SectTxt[sect]);
// char errMsg[MAXMSG+1];
// EN_geterror(214, errMsg, MAXMSG);
// sprintf(pr->Msg, "%s section: %s", errMsg, SectTxt[sect]);
sprintf(pr->Msg, "%s section: %s", geterrmsg(214, pr->Msg), SectTxt[sect]);
writeline(pr, pr->Msg);
writeline(pr, line);
errsum++;
@@ -363,101 +364,121 @@ int getpumpparams(EN_Project *pr)
**-------------------------------------------------------------
** Input: none
** Output: returns error code
** Purpose: computes & checks pump curve parameters
** Purpose: computes pump curve coefficients for all pumps
**--------------------------------------------------------------
*/
{
int i, j = 0, k, m, n = 0;
double a, b, c, h0 = 0.0, h1 = 0.0, h2 = 0.0, q1 = 0.0, q2 = 0.0;
char errMsg[MAXMSG+1];
Spump *pump;
Slink *link;
Scurve *curve;
EN_Network *net = &pr->network;
for (i = 1; i <= net->Npumps; i++) {
pump = &net->Pump[i];
k = pump->Link;
link = &net->Link[k];
if (pump->Ptype == CONST_HP) { /* Constant Hp pump */
pump->H0 = 0.0;
pump->R = -8.814 * link->Km;
pump->N = -1.0;
pump->Hmax = BIG; /* No head limit */
pump->Qmax = BIG; /* No flow limit */
pump->Q0 = 1.0; /* Init. flow = 1 cfs */
continue;
}
else if (pump->Ptype == NOCURVE) { /* Pump curve specified */
j = pump->Hcurve; /* Get index of head curve */
if (j == 0) { /* Error: No head curve */
EN_geterror(226, errMsg, MAXMSG);
sprintf(pr->Msg, "%s link: %s", errMsg, link->ID);
writeline(pr, pr->Msg);
return (200);
}
curve = &net->Curve[j];
curve->Type = P_CURVE;
n = curve->Npts;
if (n == 1) { /* Only a single h-q point supplied so use generic */
pump->Ptype = POWER_FUNC; /* power function curve. */
q1 = curve->X[0];
h1 = curve->Y[0];
h0 = 1.33334 * h1;
q2 = 2.0 * q1;
h2 = 0.0;
} else if (n == 3 && curve->X[0] == 0.0) /* 3 h-q points supplied with */
{ /* shutoff head so use fitted */
pump->Ptype = POWER_FUNC; /* power function curve. */
h0 = curve->Y[0];
q1 = curve->X[1];
h1 = curve->Y[1];
q2 = curve->X[2];
h2 = curve->Y[2];
}
else { // use a custom curve, referenced by ID
pump->Ptype = CUSTOM; /* Else use custom pump curve.*/
// at this point, j is set to that curve's index.
}
/* Compute shape factors & limits of power function pump curves */
if (pump->Ptype == POWER_FUNC) {
if (!powercurve(h0, h1, h2, q1, q2, &a, &b, &c)) { /* Error: Invalid curve */
EN_geterror(227, errMsg, MAXMSG);
sprintf(pr->Msg, "%s link: %s", errMsg, link->ID);
writeline(pr, pr->Msg);
return (200);
} else {
pump->H0 = -a;
pump->R = -b;
pump->N = c;
pump->Q0 = q1;
pump->Qmax = pow((-a / b), (1.0 / c));
pump->Hmax = h0;
int i, k, errcode = 0;
EN_Network *net = &pr->network;
for (i = 1; i <= net->Npumps; i++)
{
errcode = updatepumpparams(pr, i);
if (errcode)
{
k = net->Pump[i].Link;
sprintf(pr->Msg, "%s link: %s", geterrmsg(errcode, pr->Msg),
net->Link[k].ID);
writeline(pr, pr->Msg);
return 200;
}
}
}
return 0;
}
int updatepumpparams(EN_Project *pr, int pumpindex)
/*
**-------------------------------------------------------------
** Input: pumpindex = index of a pump
** Output: returns error code
** Purpose: computes & checks a pump's head curve coefficients
**--------------------------------------------------------------
*/
{
int m;
int curveindex;
int npts = 0;
int errcode = 0;
double a, b, c, h0 = 0.0, h1 = 0.0, h2 = 0.0, q1 = 0.0, q2 = 0.0;
EN_Network *net = &pr->network;
Spump *pump;
Scurve *curve;
pump = &net->Pump[pumpindex];
if (pump->Ptype == CONST_HP) // Constant Hp pump
{
pump->H0 = 0.0;
pump->R = -8.814 * net->Link[pump->Link].Km;
pump->N = -1.0;
pump->Hmax = BIG; // No head limit
pump->Qmax = BIG; // No flow limit
pump->Q0 = 1.0; // Init. flow = 1 cfs
return errcode;
}
/* Assign limits to custom pump curves */
if (pump->Ptype == CUSTOM) {
curve = &net->Curve[j];
for (m = 1; m < n; m++) {
if (curve->Y[m] >= curve->Y[m - 1]) { /* Error: Invalid curve */
EN_geterror(227, errMsg, MAXMSG);
sprintf(pr->Msg, "%s link: %s", errMsg, link->ID);
writeline(pr, pr->Msg);
return (200);
else if (pump->Ptype == NOCURVE) // Pump curve specified
{
curveindex = pump->Hcurve;
if (curveindex == 0) return 226;
curve = &net->Curve[curveindex];
curve->Type = P_CURVE;
npts = curve->Npts;
// Generic power function curve
if (npts == 1)
{
pump->Ptype = POWER_FUNC;
q1 = curve->X[0];
h1 = curve->Y[0];
h0 = 1.33334 * h1;
q2 = 2.0 * q1;
h2 = 0.0;
}
// 3 point curve with shutoff head
else if (npts == 3 && curve->X[0] == 0.0)
{
pump->Ptype = POWER_FUNC;
h0 = curve->Y[0];
q1 = curve->X[1];
h1 = curve->Y[1];
q2 = curve->X[2];
h2 = curve->Y[2];
}
// Custom pump curve
else
{
pump->Ptype = CUSTOM;
for (m = 1; m < npts; m++)
{
if (curve->Y[m] >= curve->Y[m - 1]) return 227;
}
pump->Qmax = curve->X[npts - 1];
pump->Q0 = (curve->X[0] + pump->Qmax) / 2.0;
pump->Hmax = curve->Y[0];
}
// Compute shape factors & limits of power function curves
if (pump->Ptype == POWER_FUNC)
{
if (!powercurve(h0, h1, h2, q1, q2, &a, &b, &c)) return 227;
else
{
pump->H0 = -a;
pump->R = -b;
pump->N = c;
pump->Q0 = q1;
pump->Qmax = pow((-a / b), (1.0 / c));
pump->Hmax = h0;
}
}
}
pump->Qmax = curve->X[n - 1];
pump->Q0 = (curve->X[0] + pump->Qmax) / 2.0;
pump->Hmax = curve->Y[0];
}
} /* Next pump */
return (0);
return 0;
}
int addnodeID(EN_Network *net, int n, char *id)
/*
**-------------------------------------------------------------
@@ -603,7 +624,6 @@ int unlinked(EN_Project *pr)
EN_Network *net = &pr->network;
int *marked;
int i, err, errcode;
char errMsg[MAXMSG+1];
errcode = 0;
err = 0;
@@ -621,8 +641,7 @@ int unlinked(EN_Project *pr)
if (marked[i] == 0) /* If not marked then error */
{
err++;
EN_geterror(233, errMsg, MAXMSG);
sprintf(pr->Msg, "%s node: %s", errMsg, net->Node[i].ID);
sprintf(pr->Msg, "%s link: %s", geterrmsg(233, pr->Msg), net->Node[i].ID);
writeline(pr, pr->Msg);
}
if (err >= MAXERRS)
@@ -732,9 +751,7 @@ int getcurves(EN_Project *pr)
/* Check that curve has data points */
if (curve->Npts <= 0) {
char errMsg[MAXMSG+1];
EN_geterror(230, errMsg, MAXMSG);
sprintf(pr->Msg, "%s curve: %s", errMsg, curve->ID);
sprintf(pr->Msg, "%s link: %s", geterrmsg(230, pr->Msg), curve->ID);
writeline(pr, pr->Msg);
return (200);
}
@@ -754,9 +771,7 @@ int getcurves(EN_Project *pr)
/* Check that x data is in ascending order */
if (fx->value >= x) {
char errMsg[MAXMSG+1];
EN_geterror(230, errMsg, MAXMSG);
sprintf(pr->Msg, "%s node: %s", errMsg, curve->ID);
sprintf(pr->Msg, "%s link: %s", geterrmsg(230, pr->Msg), curve->ID);
writeline(pr, pr->Msg);
return (200);
}
@@ -1012,10 +1027,8 @@ void inperrmsg(EN_Project *pr, int err, int sect, char *line)
char errStr[MAXMSG + 1];
char id[MAXMSG + 1];
EN_geterror(err, errStr, MAXMSG);
/* get text for error message */
sprintf(pr->Msg, "%s - section: %s", errStr, SectTxt[sect]);
sprintf(pr->Msg, "%s - section: %s", geterrmsg(err, errStr), SectTxt[sect]);
// append ID?
/* Retrieve ID label of object with input error */

View File

@@ -82,8 +82,6 @@ int writereport(EN_Project *pr)
/* write formatted output to primary report file. */
rep->Fprinterr = FALSE;
if (rep->Rptflag && strlen(rep->Rpt2Fname) == 0 && rep->RptFile != NULL) {
writecon(FMT17);
writecon(rep->Rpt1Fname);
if (rep->Energyflag)
writeenergy(pr);
errcode = writeresults(pr);
@@ -95,8 +93,6 @@ int writereport(EN_Project *pr)
/* If secondary report file has same name as either input */
/* or primary report file then use primary report file. */
if (strcomp(rep->Rpt2Fname, par->InpFname) || strcomp(rep->Rpt2Fname, rep->Rpt1Fname)) {
writecon(FMT17);
writecon(rep->Rpt1Fname);
if (rep->Energyflag)
writeenergy(pr);
errcode = writeresults(pr);
@@ -117,8 +113,6 @@ int writereport(EN_Project *pr)
/* Write full formatted report to file */
else {
rep->Rptflag = 1;
writecon(FMT17);
writecon(rep->Rpt2Fname);
writelogo(pr);
if (rep->Summaryflag)
writesummary(pr);

View File

@@ -449,19 +449,15 @@ AUTHOR: L. Rossman
#define FMT82 "\n\f\n Page %-d %60.60s\n"
/* ------------------- Progress Messages ---------------------- */
#define FMT100 "Retrieving network data..."
#define FMT101 "Computing hydraulics at hour %s"
#define FMT102 "Computing water quality at hour %s"
#define FMT103 "Saving results to file..."
#define FMT100 " Retrieving network data ... "
#define FMT101 " Computing hydraulics at hour %-10s "
#define FMT102 " Computing water quality at hour %-10s "
#define FMT103 " Writing output report ... "
#define FMT106 " Transferring results to file ... "
#define FMT104 "Analysis begun %s"
#define FMT105 "Analysis ended %s"
/*------------------- Error Messages --------------------*/
#define R_ERR201 "Input Error 201: syntax error in following line of "
#define R_ERR202 "Input Error 202: illegal numeric value in following line of "
#define R_ERR203 "Input Error 203: undefined node in following line of "

View File

@@ -51,7 +51,7 @@ typedef int INT4;
#define TITLELEN 79 // Max. # characters in a title line
#define MAXID 31 /* Max. # characters in ID name */
#define MAXMSG 255 /* Max. # characters in message text */
#define MAXLINE 255 /* Max. # characters read from input line */
#define MAXLINE 1024 /* Max. # characters read from input line */
#define MAXFNAME 259 /* Max. # characters in file name */
#define MAXTOKS 40 /* Max. items per line of input */
#define TZERO 1.E-4 /* Zero time tolerance */

100
tests/test_setlinktype.cpp Normal file
View File

@@ -0,0 +1,100 @@
// Test of ENsetlinktype EPANET API Function
#define _CRT_SECURE_NO_DEPRECATE
/*
This is a test for the API function that changes a link's type.
Two links in Net1.inp are changed: Pipe 113 is reversed with a CV added
and Pipe 121 is changed to a 100 psi PRV. After running the revised model,
at hour 0 the flow in Pipe 113 should be zero and the pressure at node 31
of the PRV 121 should be 100.
*/
#define BOOST_TEST_MODULE "toolkit"
#include <boost/test/included/unit_test.hpp>
#include <string>
#include "epanet2.h"
#define DATA_PATH_INP "./net1.inp"
#define DATA_PATH_RPT "./test.rpt"
#define DATA_PATH_OUT "./test.out"
using namespace std;
BOOST_AUTO_TEST_SUITE (test_toolkit)
BOOST_AUTO_TEST_CASE(test_setlinktype)
{
int error = 0;
int p113, n31, p121, n113_1, n113_2;
float q113 = 0.0f, p31 = 0.0f, diam;
EN_ProjectHandle ph = NULL;
EN_createproject(&ph);
std::string path_inp = std::string(DATA_PATH_INP);
std::string path_rpt = std::string(DATA_PATH_RPT);
std::string path_out = std::string(DATA_PATH_OUT);
error = EN_open(ph, path_inp.c_str(), path_rpt.c_str(), "");
BOOST_REQUIRE(error == 0);
// Change duration to 0
error = EN_settimeparam(ph, EN_DURATION, 0);
BOOST_REQUIRE(error == 0);
// Get indexes of pipe 113 and node 31
error = EN_getlinkindex(ph, (char *)"113", &p113);
BOOST_REQUIRE(error == 0);
error = EN_getnodeindex(ph, (char *)"31", &n31);
BOOST_REQUIRE(error == 0);
// Reverse pipe 113 and give it a check valve
error = EN_getlinknodes(ph, p113, &n113_1, &n113_2);
BOOST_REQUIRE(error == 0);
error = EN_setlinknodes(ph, p113, n113_2, n113_1);
BOOST_REQUIRE(error == 0);
error = EN_setlinktype(ph, &p113, EN_CVPIPE);
BOOST_REQUIRE(error == 0);
// Get index & diameter of pipe 121 connected to node 31
error = EN_getlinkindex(ph, (char *)"121", &p121);
BOOST_REQUIRE(error == 0);
error = EN_getlinkvalue(ph, p121, EN_DIAMETER, &diam);
BOOST_REQUIRE(error == 0);
// Replace it with a PRV
error = EN_setlinktype(ph, &p121, EN_PRV);
BOOST_REQUIRE(error == 0);
// Set diameter & setting of new PRV
error = EN_setlinkvalue(ph, p121, EN_INITSETTING, 100);
BOOST_REQUIRE(error == 0);
error = EN_setlinkvalue(ph, p121, EN_DIAMETER, diam);
BOOST_REQUIRE(error == 0);
// Solve for hydraulics
error = EN_solveH(ph);
BOOST_REQUIRE(error == 0);
// Get flow in link 113 and pressure at node 31
error = EN_getlinkvalue(ph, p113, EN_FLOW, &q113);
BOOST_REQUIRE(error == 0);
error = EN_getnodevalue(ph, n31, EN_PRESSURE, &p31);
BOOST_REQUIRE(error == 0);
// Require that link 113 flow be 0
q113 = fabs(q113);
BOOST_REQUIRE(q113 < 0.001);
// Require that node 31 pressure be 100
p31 = fabs(p31 - 100.0f);
BOOST_REQUIRE(p31 < 0.001);
// Close and delete project
error = EN_close(ph);
BOOST_REQUIRE(error == 0);
EN_deleteproject(&ph);
}
BOOST_AUTO_TEST_SUITE_END()