From 5f8ee49fd6480f4ecf38bd95e2d1328071d35d69 Mon Sep 17 00:00:00 2001 From: Sam Hatchett Date: Wed, 27 Jul 2022 14:18:50 -0400 Subject: [PATCH 1/5] adds an API function to get information about upcoming events --- include/epanet2_2.h | 10 ++++ include/epanet2_enums.h | 12 +++++ src/epanet.c | 107 ++++++++++++++++++++++++++-------------- src/funcs.h | 3 +- src/hydraul.c | 25 +++++----- 5 files changed, 109 insertions(+), 48 deletions(-) diff --git a/include/epanet2_2.h b/include/epanet2_2.h index 18ef127..4393073 100644 --- a/include/epanet2_2.h +++ b/include/epanet2_2.h @@ -638,6 +638,16 @@ typedef struct Project *EN_Project; */ int DLLEXPORT EN_getstatistic(EN_Project ph, int type, double* out_value); + + /** + @brief Get information about upcoming time step events, and what causes them. + @param ph an EPANET project handle. + @param[out] eventType the type of event that will occur. + @param[out] duration the amount of time in the future this event will occur + @param[out] elementIndex the index of the element causing the event. + **/ + int DLLEXPORT EN_timeToNextEvent(EN_Project ph, EN_TimestepEvent *eventType, long *duration, int *elementIndex); + /** @brief Retrieves the order in which a node or link appears in an @ref OutFile "output file". @param ph an EPANET project handle. diff --git a/include/epanet2_enums.h b/include/epanet2_enums.h index a000b0c..e0aa9ae 100644 --- a/include/epanet2_enums.h +++ b/include/epanet2_enums.h @@ -125,6 +125,18 @@ typedef enum { EN_NEXTEVENTTANK = 15 //!< Index of tank with shortest time to become empty or full (read only) } EN_TimeParameter; + +/** +These are the types of events that can cause a timestep to end. +**/ +typedef enum { + EN_STEP_REPORT = 0, + EN_STEP_HYD = 1, + EN_STEP_WQ = 2, + EN_STEP_TANKEVENT = 3, + EN_STEP_CONTROLEVENT = 4 +} EN_TimestepEvent; + /// Analysis convergence statistics /** These statistics report the convergence criteria for the most current hydraulic analysis diff --git a/src/epanet.c b/src/epanet.c index 9a3c194..9c5783c 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -1610,6 +1610,41 @@ int DLLEXPORT EN_settimeparam(EN_Project p, int param, long value) return 0; } + +/// get the time to next event, and give a reason for the time step truncation +int DLLEXPORT EN_timeToNextEvent(EN_Project p, EN_TimestepEvent *eventType, long *duration, int *elementIndex) +{ + Times *time = &p->times; + long hydStep, tankStep, controlStep; + + hydStep = time->Hstep; + tankStep = hydStep; + controlStep = hydStep; + + int iTank = tanktimestep(p, &tankStep); + int iControl = controltimestep(p, &controlStep); + + // return the lesser of the three step lengths + if (controlStep < tankStep) { + *eventType = EN_STEP_CONTROLEVENT; + *duration = controlStep; + *elementIndex = iControl; + } + else if (tankStep < hydStep) { + *eventType = EN_STEP_TANKEVENT; + *duration = tankStep; + *elementIndex = iTank; + } + else { + *eventType = EN_STEP_HYD; + *duration = hydStep; + *elementIndex = 0; + } + + return 0; +} + + int DLLEXPORT EN_getqualinfo(EN_Project p, int *qualType, char *chemName, char *chemUnits, int *traceNode) /*---------------------------------------------------------------- @@ -1774,9 +1809,9 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType, int *index) // Check if a node with same id already exists if (EN_getnodeindex(p, id, &i) == 0) return 215; - + // Check for valid node type - if (nodeType < EN_JUNCTION || nodeType > EN_TANK) return 251; + if (nodeType < EN_JUNCTION || nodeType > EN_TANK) return 251; // Grow node-related arrays to accomodate the new node size = (net->Nnodes + 2) * sizeof(Snode); @@ -1797,7 +1832,7 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType, int *index) hashtable_update(net->NodeHashTable, net->Node[i].ID, i + 1); net->Node[i + 1] = net->Node[i]; } - + // set index of new Junction node net->Njuncs++; nIdx = net->Njuncs; @@ -2254,20 +2289,20 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val if (Node[index].Type != TANK) return 0; v = Tank[index - nJuncs].CanOverflow; break; - + case EN_DEMANDDEFICIT: if (index > nJuncs) return 0; // After an analysis, DemandFlow contains node's required demand // while NodeDemand contains delivered demand + emitter flow if (hyd->DemandFlow[index] < 0.0) return 0; - v = (hyd->DemandFlow[index] - + v = (hyd->DemandFlow[index] - (hyd->NodeDemand[index] - hyd->EmitterFlow[index])) * Ucf[FLOW]; break; - + case EN_NODE_INCONTROL: v = (double)incontrols(p, NODE, index); break; - + default: return 251; } @@ -2483,7 +2518,7 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu Tank[j].Vmin = tankvolume(p, j, Tank[j].Hmin); // new min. volume Tank[j].V0 = tankvolume(p, j, Tank[j].H0); // new init. volume Tank[j].Vmax = tankvolume(p, j, Tank[j].Hmax); // new max. volume - Tank[j].A = (curve->Y[n] - curve->Y[0]) / // nominal area + Tank[j].A = (curve->Y[n] - curve->Y[0]) / // nominal area (curve->X[n] - curve->X[0]); break; @@ -3793,7 +3828,7 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val v = (double)Pump[findpump(&p->network, index)].Epat; } break; - + case EN_GPV_CURVE: if (Link[index].Type == GPV) { @@ -3804,7 +3839,7 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val case EN_LINK_INCONTROL: v = (double)incontrols(p, LINK, index); break; - + default: return 251; } @@ -4011,7 +4046,7 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu net->Pump[pumpIndex].Epat = patIndex; } break; - + case EN_GPV_CURVE: if (Link[index].Type == GPV) { @@ -4077,20 +4112,20 @@ int DLLEXPORT EN_getvertexcount(EN_Project p, int index, int *count) */ { Network *net = &p->network; - + Slink *Link = net->Link; Pvertices vertices; - + // Check that link exists *count = 0; if (!p->Openflag) return 102; if (index <= 0 || index > net->Nlinks) return 204; - + // Set count to number of vertices vertices = Link[index].Vertices; if (vertices) *count = vertices->Npts; return 0; -} +} int DLLEXPORT EN_getvertex(EN_Project p, int index, int vertex, double *x, double *y) /*---------------------------------------------------------------- @@ -4104,22 +4139,22 @@ int DLLEXPORT EN_getvertex(EN_Project p, int index, int vertex, double *x, doubl */ { Network *net = &p->network; - + Slink *Link = net->Link; Pvertices vertices; - + // Check that link exists *x = MISSING; *y = MISSING; if (!p->Openflag) return 102; if (index <= 0 || index > net->Nlinks) return 204; - + // Check that vertex exists vertices = Link[index].Vertices; if (vertices == NULL) return 255; if (vertex <= 0 || vertex > vertices->Npts) return 255; *x = vertices->X[vertex - 1]; - *y = vertices->Y[vertex - 1]; + *y = vertices->Y[vertex - 1]; return 0; } @@ -4135,23 +4170,23 @@ int DLLEXPORT EN_setvertex(EN_Project p, int index, int vertex, double x, double */ { Network *net = &p->network; - + Slink *Link = net->Link; Pvertices vertices; - + // Check that link exists if (!p->Openflag) return 102; if (index <= 0 || index > net->Nlinks) return 204; - + // Check that vertex exists vertices = Link[index].Vertices; if (vertices == NULL) return 255; if (vertex <= 0 || vertex > vertices->Npts) return 255; vertices->X[vertex - 1] = x; - vertices->Y[vertex - 1] = y; + vertices->Y[vertex - 1] = y; return 0; } - + int DLLEXPORT EN_setvertices(EN_Project p, int index, double *x, double *y, int count) /*---------------------------------------------------------------- ** Input: index = link index @@ -4164,11 +4199,11 @@ int DLLEXPORT EN_setvertices(EN_Project p, int index, double *x, double *y, int */ { Network *net = &p->network; - + Slink *link; int i; int err = 0; - + // Check that link exists if (!p->Openflag) return 102; if (index <= 0 || index > net->Nlinks) return 204; @@ -4176,7 +4211,7 @@ int DLLEXPORT EN_setvertices(EN_Project p, int index, double *x, double *y, int // Delete existing set of vertices freelinkvertices(link); - + // Add each new vertex to the link for (i = 0; i < count; i++) { @@ -4185,7 +4220,7 @@ int DLLEXPORT EN_setvertices(EN_Project p, int index, double *x, double *y, int } if (err) freelinkvertices(link); return err; -} +} /******************************************************************** @@ -4269,16 +4304,16 @@ int DLLEXPORT EN_setheadcurveindex(EN_Project p, int linkIndex, int curveIndex) pump = &p->network.Pump[pumpIndex]; oldCurveIndex = pump->Hcurve; newCurveType = p->network.Curve[curveIndex].Type; - + // Assign the new curve to the pump pump->Ptype = NOCURVE; pump->Hcurve = curveIndex; if (curveIndex == 0) return 0; - + // Update the pump's head curve parameters (which also changes // the new curve's Type to PUMP_CURVE) err = updatepumpparams(p, pumpIndex); - + // If the parameter updating failed (new curve was not a valid pump curve) // restore the pump's original curve and its parameters if (err > 0) @@ -4288,8 +4323,8 @@ int DLLEXPORT EN_setheadcurveindex(EN_Project p, int linkIndex, int curveIndex) pump->Hcurve = oldCurveIndex; if (oldCurveIndex == 0) return err; updatepumpparams(p, pumpIndex); - } - + } + // Convert the units of the updated pump parameters to feet and cfs if (pump->Ptype == POWER_FUNC) { @@ -4778,7 +4813,7 @@ int DLLEXPORT EN_setcurvetype(EN_Project p, int index, int type) Network *net = &p->network; if (!p->Openflag) return 102; if (index < 1 || index > net->Ncurves) return 206; - if (type < 0 || type > EN_GENERIC_CURVE) return 251; + if (type < 0 || type > EN_GENERIC_CURVE) return 251; net->Curve[index].Type = type; return 0; } @@ -4852,7 +4887,7 @@ int DLLEXPORT EN_setcurvevalue(EN_Project p, int curveIndex, int pointIndex, // Insert new point into curve curve->X[n] = x; curve->Y[n] = y; - + // Adjust parameters for pumps using curve as a head curve return adjustpumpparams(p, curveIndex); } @@ -4926,7 +4961,7 @@ int DLLEXPORT EN_setcurve(EN_Project p, int index, double *xValues, curve->X[j] = xValues[j]; curve->Y[j] = yValues[j]; } - + // Adjust parameters for pumps using curve as a head curve return adjustpumpparams(p, index); } diff --git a/src/funcs.h b/src/funcs.h index 366e5c7..1e6be71 100755 --- a/src/funcs.h +++ b/src/funcs.h @@ -155,6 +155,7 @@ void closehyd(Project *); void setlinkstatus(Project *, int, char, StatusType *, double *); void setlinksetting(Project *, int, double, StatusType *, double *); int tanktimestep(Project *, long *); +int controltimestep(Project *, long *); void getenergy(Project *, int, double *, double *); double tankvolume(Project *, int, double); double tankgrade(Project *, int, double); @@ -164,7 +165,7 @@ double tankgrade(Project *, int, double); void resistcoeff(Project *, int); void headlosscoeffs(Project *); void matrixcoeffs(Project *); -void emitterheadloss(Project *, int, double *, double *); +void emitterheadloss(Project *, int, double *, double *); void demandheadloss(Project *, int, double, double, double *, double *); // ------- QUALITY.C -------------------- diff --git a/src/hydraul.c b/src/hydraul.c index 36cd67b..fecc9f8 100755 --- a/src/hydraul.c +++ b/src/hydraul.c @@ -34,7 +34,6 @@ void initlinkflow(Project *, int, char, double); void demands(Project *); int controls(Project *); long timestep(Project *); -void controltimestep(Project *, long *); void ruletimestep(Project *, long *); void addenergy(Project *, long); void tanklevels(Project *, long); @@ -192,7 +191,7 @@ int runhyd(Project *pr, long *t) int iter; // Iteration count int errcode; // Error code double relerr; // Solution accuracy - + // Find new demands & control actions *t = time->Htime; demands(pr); @@ -390,7 +389,7 @@ void setlinkstatus(Project *pr, int index, char value, StatusType *s, double *k if (t == PUMP) { *k = 1.0; - // Check if a re-opened pump needs its flow reset + // Check if a re-opened pump needs its flow reset if (*s == CLOSED) resetpumpflow(pr, index); } if (t > PUMP && t != GPV) *k = MISSING; @@ -596,11 +595,11 @@ int controls(Project *pr) k1 = hyd->LinkSetting[k]; k2 = k1; if (link->Type > PIPE) k2 = control->Setting; - + // Check if a re-opened pump needs its flow reset if (link->Type == PUMP && s1 == CLOSED && s2 == OPEN) resetpumpflow(pr, k); - + if (s1 != s2 || k1 != k2) { hyd->LinkStatus[k] = s2; @@ -704,7 +703,7 @@ int tanktimestep(Project *pr, long *tstep) } -void controltimestep(Project *pr, long *tstep) +int controltimestep(Project *pr, long *tstep) /* **------------------------------------------------------------------ ** Input: *tstep = current time step @@ -717,7 +716,7 @@ void controltimestep(Project *pr, long *tstep) Network *net = &pr->network; Hydraul *hyd = &pr->hydraul; - int i, j, k, n; + int i, j, k, n, controlIndex; double h, q, v; long t, t1, t2; Slink *link; @@ -774,9 +773,14 @@ void controltimestep(Project *pr, long *tstep) k = control->Link; link = &net->Link[k]; if ( (link->Type > PIPE && hyd->LinkSetting[k] != control->Setting) - || (hyd->LinkStatus[k] != control->Status) ) *tstep = t; + || (hyd->LinkStatus[k] != control->Status) ) + { + *tstep = t; + controlIndex = i; + } } } + return controlIndex; } @@ -1009,7 +1013,7 @@ void getallpumpsenergy(Project *pr) getenergy(pr, pump->Link, &(pump->Energy.CurrentPower), &(pump->Energy.CurrentEffic)); } -} +} void tanklevels(Project *pr, long tstep) @@ -1129,6 +1133,5 @@ void resetpumpflow(Project *pr, int i) Network *net = &pr->network; Spump *pump = &net->Pump[findpump(net, i)]; if (pump->Ptype == CONST_HP) - pr->hydraul.LinkFlow[i] = pump->Q0; + pr->hydraul.LinkFlow[i] = pump->Q0; } - From 9b3007ff55f474ccab89b239473afa69617a1590 Mon Sep 17 00:00:00 2001 From: Sam Hatchett Date: Mon, 8 Aug 2022 12:02:22 -0400 Subject: [PATCH 2/5] adds projectless function declarations and fixes non-camelcase convention --- include/epanet2.h | 22 ++++++++++++---------- include/epanet2_2.h | 2 +- src/epanet.c | 2 +- src/epanet2.c | 12 ++++++++---- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/include/epanet2.h b/include/epanet2.h index 3779d66..21d553f 100644 --- a/include/epanet2.h +++ b/include/epanet2.h @@ -72,9 +72,9 @@ extern "C" { int DLLEXPORT ENopen(const char *inpFile, const char *rptFile, const char *outFile); - + int DLLEXPORT ENgettitle(char *line1, char *line2, char *line3); - + int DLLEXPORT ENsettitle(char *line1, char *line2, char *line3); int DLLEXPORT ENgetcomment(int object, int index, char *comment); @@ -156,9 +156,11 @@ extern "C" { int DLLEXPORT ENgeterror(int errcode, char *errmsg, int maxLen); int DLLEXPORT ENgetstatistic(int type, EN_API_FLOAT_TYPE* value); - + int DLLEXPORT ENgetresultindex(int type, int index, int *value); + int DLLEXPORT ENtimetonextevent(EN_TimestepEvent *eventType, long *duration, int *elementIndex); + /******************************************************************** Analysis Options Functions @@ -235,7 +237,7 @@ extern "C" { char *demandPattern, char *demandName); int DLLEXPORT ENdeletedemand(int nodeIndex, int demandIndex); - + int DLLEXPORT ENgetnumdemands(int nodeIndex, int *numDemands); int DLLEXPORT ENgetdemandindex(int nodeIndex, char *demandName, int *demandIndex); @@ -285,13 +287,13 @@ extern "C" { int DLLEXPORT ENsetpipedata(int index, EN_API_FLOAT_TYPE length, EN_API_FLOAT_TYPE diam, EN_API_FLOAT_TYPE rough, EN_API_FLOAT_TYPE mloss); - + int DLLEXPORT ENgetvertexcount(int index, int *count); - + int DLLEXPORT ENgetvertex(int index, int vertex, double *x, double *y); - + int DLLEXPORT ENsetvertex(int index, int vertex, double x, double y); - + int DLLEXPORT ENsetvertices(int index, double *x, double *y, int count); /******************************************************************** @@ -351,7 +353,7 @@ extern "C" { int DLLEXPORT ENgetcurvelen(int index, int *len); int DLLEXPORT ENgetcurvetype(int index, int *type); - + int DLLEXPORT ENsetcurvetype(int index, int type); int DLLEXPORT ENgetcurvevalue(int curveIndex, int pointIndex, @@ -425,7 +427,7 @@ extern "C" { int DLLEXPORT ENsetelseaction(int ruleIndex, int actionIndex, int linkIndex, int status, EN_API_FLOAT_TYPE setting); - + int DLLEXPORT ENsetrulepriority(int index, EN_API_FLOAT_TYPE priority); #if defined(__cplusplus) diff --git a/include/epanet2_2.h b/include/epanet2_2.h index 4393073..3306b95 100644 --- a/include/epanet2_2.h +++ b/include/epanet2_2.h @@ -646,7 +646,7 @@ typedef struct Project *EN_Project; @param[out] duration the amount of time in the future this event will occur @param[out] elementIndex the index of the element causing the event. **/ - int DLLEXPORT EN_timeToNextEvent(EN_Project ph, EN_TimestepEvent *eventType, long *duration, int *elementIndex); + int DLLEXPORT EN_timetonextevent(EN_Project ph, EN_TimestepEvent *eventType, long *duration, int *elementIndex); /** @brief Retrieves the order in which a node or link appears in an @ref OutFile "output file". diff --git a/src/epanet.c b/src/epanet.c index 9c5783c..b8fa26d 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -1612,7 +1612,7 @@ int DLLEXPORT EN_settimeparam(EN_Project p, int param, long value) /// get the time to next event, and give a reason for the time step truncation -int DLLEXPORT EN_timeToNextEvent(EN_Project p, EN_TimestepEvent *eventType, long *duration, int *elementIndex) +int DLLEXPORT EN_timetonextevent(EN_Project p, EN_TimestepEvent *eventType, long *duration, int *elementIndex) { Times *time = &p->times; long hydStep, tankStep, controlStep; diff --git a/src/epanet2.c b/src/epanet2.c index 1706936..d3a3f86 100644 --- a/src/epanet2.c +++ b/src/epanet2.c @@ -232,6 +232,10 @@ int DLLEXPORT ENgetresultindex(int type, int index, int *value) return EN_getresultindex(_defaultProject, type, index, value); } +int DLLEXPORT ENtimetonextevent(EN_TimestepEvent *eventType, long *duration, int *elementIndex) +{ + return EN_timetonextevent(_defaultProject, eventType, duration, elementIndex); +} /******************************************************************** @@ -516,7 +520,7 @@ int DLLEXPORT ENgetvertexcount(int index, int *count) { return EN_getvertexcount(_defaultProject, index, count); } - + int DLLEXPORT ENgetvertex(int index, int vertex, double *x, double *y) { return EN_getvertex(_defaultProject, index, vertex, x, y); @@ -530,7 +534,7 @@ int DLLEXPORT ENsetvertex(int index, int vertex, double x, double y) int DLLEXPORT ENsetvertices(int index, double *x, double *y, int count) { return EN_setvertices(_defaultProject, index, x, y, count); -} +} /******************************************************************** @@ -714,10 +718,10 @@ int DLLEXPORT ENsetcurve(int index, EN_API_FLOAT_TYPE *xValues, double *xx = NULL; double *yy = NULL; int i, errcode = 0; - + if (xValues == NULL || yValues == NULL) return 206; if (nPoints < 1) return 202; - + xx = (double *)calloc(nPoints, sizeof(double)); yy = (double *)calloc(nPoints, sizeof(double)); if (xx && yy) From 736f5ebdd45668686f7154da56c3d24503e31f98 Mon Sep 17 00:00:00 2001 From: Sam Hatchett Date: Thu, 19 Jan 2023 09:50:50 -0500 Subject: [PATCH 3/5] updates function signatures to use int-casted enum --- include/epanet2.h | 2 +- include/epanet2_2.h | 4 ++-- src/epanet.c | 8 ++++---- src/epanet2.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/epanet2.h b/include/epanet2.h index 21d553f..c8d023f 100644 --- a/include/epanet2.h +++ b/include/epanet2.h @@ -159,7 +159,7 @@ extern "C" { int DLLEXPORT ENgetresultindex(int type, int index, int *value); - int DLLEXPORT ENtimetonextevent(EN_TimestepEvent *eventType, long *duration, int *elementIndex); + int DLLEXPORT ENtimetonextevent(int *eventType, long *duration, int *elementIndex); /******************************************************************** diff --git a/include/epanet2_2.h b/include/epanet2_2.h index 3306b95..4f49d1a 100644 --- a/include/epanet2_2.h +++ b/include/epanet2_2.h @@ -642,11 +642,11 @@ typedef struct Project *EN_Project; /** @brief Get information about upcoming time step events, and what causes them. @param ph an EPANET project handle. - @param[out] eventType the type of event that will occur. + @param[out] eventType the type of event that will occur (see @ref EN_TimestepEvent). @param[out] duration the amount of time in the future this event will occur @param[out] elementIndex the index of the element causing the event. **/ - int DLLEXPORT EN_timetonextevent(EN_Project ph, EN_TimestepEvent *eventType, long *duration, int *elementIndex); + int DLLEXPORT EN_timetonextevent(EN_Project ph, int *eventType, long *duration, int *elementIndex); /** @brief Retrieves the order in which a node or link appears in an @ref OutFile "output file". diff --git a/src/epanet.c b/src/epanet.c index b8fa26d..fb3861e 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -1612,7 +1612,7 @@ int DLLEXPORT EN_settimeparam(EN_Project p, int param, long value) /// get the time to next event, and give a reason for the time step truncation -int DLLEXPORT EN_timetonextevent(EN_Project p, EN_TimestepEvent *eventType, long *duration, int *elementIndex) +int DLLEXPORT EN_timetonextevent(EN_Project p, int *eventType, long *duration, int *elementIndex) { Times *time = &p->times; long hydStep, tankStep, controlStep; @@ -1626,17 +1626,17 @@ int DLLEXPORT EN_timetonextevent(EN_Project p, EN_TimestepEvent *eventType, lon // return the lesser of the three step lengths if (controlStep < tankStep) { - *eventType = EN_STEP_CONTROLEVENT; + *eventType = (int)EN_STEP_CONTROLEVENT; *duration = controlStep; *elementIndex = iControl; } else if (tankStep < hydStep) { - *eventType = EN_STEP_TANKEVENT; + *eventType = (int)EN_STEP_TANKEVENT; *duration = tankStep; *elementIndex = iTank; } else { - *eventType = EN_STEP_HYD; + *eventType = (int)EN_STEP_HYD; *duration = hydStep; *elementIndex = 0; } diff --git a/src/epanet2.c b/src/epanet2.c index d3a3f86..3534d70 100644 --- a/src/epanet2.c +++ b/src/epanet2.c @@ -232,7 +232,7 @@ int DLLEXPORT ENgetresultindex(int type, int index, int *value) return EN_getresultindex(_defaultProject, type, index, value); } -int DLLEXPORT ENtimetonextevent(EN_TimestepEvent *eventType, long *duration, int *elementIndex) +int DLLEXPORT ENtimetonextevent(int *eventType, long *duration, int *elementIndex) { return EN_timetonextevent(_defaultProject, eventType, duration, elementIndex); } From e2df3e87ace62351446276a6d90e25c5edc5741c Mon Sep 17 00:00:00 2001 From: Elad Salomons Date: Thu, 19 Jan 2023 20:45:30 +0200 Subject: [PATCH 4/5] Adding support for VB Also supporting C89 compiler. --- include/epanet2.bas | 7 +++++++ include/epanet2.def | 1 + src/epanet.c | 7 ++++--- src/report.c | 4 ++-- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/epanet2.bas b/include/epanet2.bas index bc2ce1e..2d41bb2 100644 --- a/include/epanet2.bas +++ b/include/epanet2.bas @@ -253,6 +253,12 @@ Public Const EN_R_IS_OPEN = 1 ' Rule status types Public Const EN_R_IS_CLOSED = 2 Public Const EN_R_IS_ACTIVE = 3 +Public Const EN_STEP_REPORT = 0 ' Types of events that can cause a timestep to end +Public Const EN_STEP_HYD = 1 +Public Const EN_STEP_WQ = 2 +Public Const EN_STEP_TANKEVENT = 3 +Public Const EN_STEP_CONTROLEVENT = 4 + Public Const EN_MISSING As Double = -1.0E10 'These are the external functions that comprise the DLL @@ -302,6 +308,7 @@ Public Const EN_MISSING As Double = -1.0E10 Declare Function ENgeterror Lib "epanet2.dll" (ByVal errcode As Long, ByVal errmsg As String, ByVal maxLen As Long) As Long Declare Function ENgetstatistic Lib "epanet2.dll" (ByVal type_ As Long, ByRef value As Single) As Long Declare Function ENgetresultindex Lib "epanet2.dll" (ByVal type_ As Long, ByVal index As Long, ByRef value As Long) As Long + Declare Function ENtimetonextevent Lib "epanet2.dll" (eventType As Long, duration As Long, elementIndex As Long) As Long 'Analysis Options Functions Declare Function ENgetoption Lib "epanet2.dll" (ByVal option_ As Long, value As Single) As Long diff --git a/include/epanet2.def b/include/epanet2.def index 66b87ed..d72da8e 100644 --- a/include/epanet2.def +++ b/include/epanet2.def @@ -131,3 +131,4 @@ EXPORTS ENstepQ = _ENstepQ@4 ENusehydfile = _ENusehydfile@4 ENwriteline = _ENwriteline@4 + ENtimetonextevent = _ENtimetonextevent@12 \ No newline at end of file diff --git a/src/epanet.c b/src/epanet.c index a5c83ac..6516f7a 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -1629,13 +1629,14 @@ int DLLEXPORT EN_timetonextevent(EN_Project p, int *eventType, long *duration, { Times *time = &p->times; long hydStep, tankStep, controlStep; - + int iTank, iControl; + hydStep = time->Hstep; tankStep = hydStep; controlStep = hydStep; - int iTank = tanktimestep(p, &tankStep); - int iControl = controltimestep(p, &controlStep); + iTank = tanktimestep(p, &tankStep); + iControl = controltimestep(p, &controlStep); // return the lesser of the three step lengths if (controlStep < tankStep) { diff --git a/src/report.c b/src/report.c index 2922332..ae675da 100644 --- a/src/report.c +++ b/src/report.c @@ -885,14 +885,14 @@ void writeline(Project *pr, char *s) **-------------------------------------------------------------- */ { + Report *rpt = &pr->report; + if (pr->report.reportCallback != NULL) { pr->report.reportCallback(pr->report.reportCallbackUserData, pr, s); return; } - Report *rpt = &pr->report; - if (rpt->RptFile == NULL) return; if (rpt->Rptflag) { From 57ae3eeab8ed9d3834688776f72d3f5f46c05904 Mon Sep 17 00:00:00 2001 From: Sam Hatchett Date: Thu, 19 Jan 2023 14:16:50 -0500 Subject: [PATCH 5/5] Update ReleaseNotes2_3.md --- ReleaseNotes2_3.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ReleaseNotes2_3.md b/ReleaseNotes2_3.md index 5a3b2d3..2a51cd6 100644 --- a/ReleaseNotes2_3.md +++ b/ReleaseNotes2_3.md @@ -25,6 +25,7 @@ This document describes the changes and updates that have been made in version 2 - A possible loss of network connectivity when evaluating a Pressure Sustaining Valve was prevented. - Having the implied loss coefficient for an active Flow Control Valve be less than its fully opened value was prevented. - A new type of valve, a Positional Control Valve (PCV), was added that uses a valve characteristic curve to relate its loss coefficient to its fraction open setting. - + - A new set of functions have been added to get information about upcoming time step events. Users will now see what type of event is going to cause the end of a time step to occur. See ENtimetonextevent and EN_timetonextevent. + - A new set of functions have been added to allow users to set a reporting callback function. The user-supplied function will recieve all output normally directed to the report file.