diff --git a/README.md b/README.md index 7f33dc6..65fa407 100755 --- a/README.md +++ b/README.md @@ -30,4 +30,4 @@ The **Open Water Analytics** (OWA) Community is an international group of EPANET ## DISCLAIMER Although OWA is not formally affiliated with nor endorsed by USEPA, this project has been a collaborative effort between the two that builds upon and extends the USEPA’s legacy EPANET 2.0 code base. For the last "official" release of EPANET please go to the [USEPA website](http://www2.epa.gov/water-research/epanet). -For more general community discussion, FAQ, and roadmapping of the project, please go to the [Community Forum](http://community/wateranalytics.org). +For more general community discussion, FAQ, and roadmapping of the project, please go to the [Community Forum](http://community.wateranalytics.org). diff --git a/include/epanet2.bas b/include/epanet2.bas index 7b40f36..d3fc17e 100644 --- a/include/epanet2.bas +++ b/include/epanet2.bas @@ -25,7 +25,6 @@ Public Const EN_SOURCEMASS = 13 Public Const EN_INITVOLUME = 14 Public Const EN_MIXMODEL = 15 Public Const EN_MIXZONEVOL = 16 - Public Const EN_TANKDIAM = 17 Public Const EN_MINVOLUME = 18 Public Const EN_VOLCURVE = 19 @@ -37,6 +36,7 @@ Public Const EN_TANKVOLUME = 24 Public Const EN_MAXVOLUME = 25 Public Const EN_CANOVERFLOW = 26 Public Const EN_DEMANDDEFICIT = 27 +Public Const EN_NODE_INCONTROL = 28 Public Const EN_DIAMETER = 0 ' Link parameters Public Const EN_LENGTH = 1 @@ -54,7 +54,6 @@ Public Const EN_SETTING = 12 Public Const EN_ENERGY = 13 Public Const EN_LINKQUAL = 14 Public Const EN_LINKPATTERN = 15 - Public Const EN_PUMP_STATE = 16 Public Const EN_PUMP_EFFIC = 17 Public Const EN_PUMP_POWER = 18 @@ -62,7 +61,8 @@ Public Const EN_PUMP_HCURVE = 19 Public Const EN_PUMP_ECURVE = 20 Public Const EN_PUMP_ECOST = 21 Public Const EN_PUMP_EPAT = 22 -Public Const EN_GPV_CURVE = 23 +Public Const EN_LINK_INCONTROL = 23 +Public Const EN_GPV_CURVE = 24 Public Const EN_DURATION = 0 ' Time parameters Public Const EN_HYDSTEP = 1 @@ -79,6 +79,7 @@ Public Const EN_HTIME = 11 Public Const EN_QTIME = 12 Public Const EN_HALTFLAG = 13 Public Const EN_NEXTEVENT = 14 +Public Const EN_NEXTEVENTTANK = 15 Public Const EN_ITERATIONS = 0 ' Run statistics Public Const EN_RELATIVEERROR = 1 @@ -117,6 +118,14 @@ Public Const EN_FCV = 6 Public Const EN_TCV = 7 Public Const EN_GPV = 8 +Public Const EN_CLOSED = 0 ' Link status types +Public Const EN_OPEN = 1 + +Public Const EN_PUMP_XHEAD = 0 ' Pump state types +Public Const EN_PUMP_CLOSED = 2 +Public Const EN_PUMP_OPEN = 3 +Public Const EN_PUMP_XFLOW = 5 + Public Const EN_NONE = 0 ' Quality analysis types Public Const EN_CHEM = 1 Public Const EN_AGE = 2 @@ -174,7 +183,8 @@ Public Const EN_HILEVEL = 1 Public Const EN_TIMER = 2 Public Const EN_TIMEOFDAY = 3 -Public Const EN_AVERAGE = 1 ' Time statistic types +Public Const EN_SERIES = 0 ' Time statistic types +Public Const EN_AVERAGE = 1 Public Const EN_MINIMUM = 2 Public Const EN_MAXIMUM = 3 Public Const EN_RANGE = 4 diff --git a/include/epanet2.pas b/include/epanet2.pas index 6eaf7bb..cbba41e 100644 --- a/include/epanet2.pas +++ b/include/epanet2.pas @@ -31,7 +31,6 @@ const EN_INITVOLUME = 14; EN_MIXMODEL = 15; EN_MIXZONEVOL = 16; - EN_TANKDIAM = 17; EN_MINVOLUME = 18; EN_VOLCURVE = 19; @@ -42,7 +41,8 @@ const EN_TANKVOLUME = 24; EN_MAXVOLUME = 25; EN_CANOVERFLOW = 26; - EN_DEMANDDEFICIT = 27; + EN_DEMANDDEFICIT = 27; + EN_NODE_INCONTROL = 28; EN_DIAMETER = 0; { Link parameters } EN_LENGTH = 1; @@ -67,7 +67,8 @@ const EN_PUMP_ECURVE = 20; EN_PUMP_ECOST = 21; EN_PUMP_EPAT = 22; - EN_GPV_CURVE = 23; + EN_LINK_INCONTROL = 23; + EN_GPV_CURVE = 24; EN_DURATION = 0; { Time parameters } EN_HYDSTEP = 1; diff --git a/include/epanet2.vb b/include/epanet2.vb index 5d721bc..bbd365e 100644 --- a/include/epanet2.vb +++ b/include/epanet2.vb @@ -29,7 +29,6 @@ Public Const EN_SOURCEMASS = 13 Public Const EN_INITVOLUME = 14 Public Const EN_MIXMODEL = 15 Public Const EN_MIXZONEVOL = 16 - Public Const EN_TANKDIAM = 17 Public Const EN_MINVOLUME = 18 Public Const EN_VOLCURVE = 19 @@ -37,11 +36,11 @@ Public Const EN_MINLEVEL = 20 Public Const EN_MAXLEVEL = 21 Public Const EN_MIXFRACTION = 22 Public Const EN_TANK_KBULK = 23 - Public Const EN_TANKVOLUME = 24 Public Const EN_MAXVOLUME = 25 Public Const EN_CANOVERFLOW = 26 -Public Const EN_DEMANDDEFICIT = 27 +Public Const EN_DEMANDDEFICIT = 27 +Public Const EN_NODE_INCONTROL = 28 Public Const EN_DIAMETER = 0 ' Link parameters Public Const EN_LENGTH = 1 @@ -59,7 +58,6 @@ Public Const EN_SETTING = 12 Public Const EN_ENERGY = 13 Public Const EN_LINKQUAL = 14 Public Const EN_LINKPATTERN = 15 - Public Const EN_PUMP_STATE = 16 Public Const EN_PUMP_EFFIC = 17 Public Const EN_PUMP_POWER = 18 @@ -67,7 +65,8 @@ Public Const EN_PUMP_HCURVE = 19 Public Const EN_PUMP_ECURVE = 20 Public Const EN_PUMP_ECOST = 21 Public Const EN_PUMP_EPAT = 22 -Public Const EN_GPV_CURVE = 23 +Public Const EN_LINK_INCONTROL = 23 +Public Const EN_GPV_CURVE = 24 Public Const EN_DURATION = 0 ' Time parameters Public Const EN_HYDSTEP = 1 diff --git a/include/epanet2_enums.h b/include/epanet2_enums.h index 7a665b6..53a3103 100644 --- a/include/epanet2_enums.h +++ b/include/epanet2_enums.h @@ -63,7 +63,8 @@ typedef enum { EN_TANKVOLUME = 24, //!< Current computed tank volume (read only) EN_MAXVOLUME = 25, //!< Tank maximum volume (read only) EN_CANOVERFLOW = 26, //!< Tank can overflow (= 1) or not (= 0) - EN_DEMANDDEFICIT = 27 //!< Amount that full demand is reduced under PDA (read only) + EN_DEMANDDEFICIT = 27,//!< Amount that full demand is reduced under PDA (read only) + EN_NODE_INCONTROL = 28 //!< Is present in any simple or rule-based control (= 1) or not (= 0) } EN_NodeProperty; /// Link properties @@ -95,7 +96,8 @@ typedef enum { EN_PUMP_ECURVE = 20, //!< Pump efficiency v. flow curve index EN_PUMP_ECOST = 21, //!< Pump average energy price EN_PUMP_EPAT = 22, //!< Pump energy price time pattern index - EN_GPV_CURVE = 23 //!< GPV head loss v. flow curve index + EN_LINK_INCONTROL = 23, //!< Is present in any simple or rule-based control (= 1) or not (= 0) + EN_GPV_CURVE = 24 //!< GPV head loss v. flow curve index } EN_LinkProperty; /// Time parameters diff --git a/src/epanet.c b/src/epanet.c index 82ece34..00c0f41 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -1591,6 +1591,11 @@ int DLLEXPORT EN_settimeparam(EN_Project p, int param, long value) time->Qtime = value; break; + case EN_STARTTIME: + if (value < 0 || value > SECperDAY) return 213; + time->Tstart = value; + break; + default: return 251; } @@ -1772,6 +1777,8 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType, int *index) hyd->NodeDemand = (double *)realloc(hyd->NodeDemand, size); qual->NodeQual = (double *)realloc(qual->NodeQual, size); hyd->NodeHead = (double *)realloc(hyd->NodeHead, size); + hyd->DemandFlow = (double *)realloc(hyd->DemandFlow, size); + hyd->EmitterFlow = (double *)realloc(hyd->EmitterFlow, size); // Actions taken when a new Junction is added if (nodeType == EN_JUNCTION) @@ -2247,6 +2254,10 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val (hyd->NodeDemand[index] - hyd->EmitterFlow[index])) * Ucf[FLOW]; break; + case EN_NODE_INCONTROL: + v = (double)incontrols(p, NODE, index); + break; + default: return 251; } @@ -2621,8 +2632,8 @@ int DLLEXPORT EN_settankdata(EN_Project p, int index, double elev, Network *net = &p->network; int i, j, n, curveIndex = 0; - double area, elevation = elev; double *Ucf = p->Ucf; + double area; Stank *Tank = net->Tank; Scurve *curve; @@ -2659,11 +2670,11 @@ int DLLEXPORT EN_settankdata(EN_Project p, int index, double elev, else area = PI * diam * diam / 4.0; // Assign parameters to tank object - net->Node[Tank[j].Node].El = elevation; + net->Node[Tank[j].Node].El = elev / Ucf[ELEV]; Tank[j].A = area / Ucf[ELEV] / Ucf[ELEV]; - Tank[j].H0 = elevation + initlvl / Ucf[ELEV]; - Tank[j].Hmin = elevation + minlvl / Ucf[ELEV]; - Tank[j].Hmax = elevation + maxlvl / Ucf[ELEV]; + Tank[j].H0 = (elev + initlvl) / Ucf[ELEV]; + Tank[j].Hmin = (elev + minlvl) / Ucf[ELEV]; + Tank[j].Hmax = (elev + maxlvl) / Ucf[ELEV]; Tank[j].Vcurve = curveIndex; if (curveIndex == 0) { @@ -3631,7 +3642,8 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val { return EN_getlinkvalue(p, index, EN_ROUGHNESS, value); } - v = Link[index].Kc; + if (Link[index].Kc == MISSING) v = 0.0; + else v = Link[index].Kc; switch (Link[index].Type) { case PRV: @@ -3785,6 +3797,10 @@ int DLLEXPORT EN_getlinkvalue(EN_Project p, int index, int property, double *val v = Link[index].Kc; } + case EN_LINK_INCONTROL: + v = (double)incontrols(p, LINK, index); + break; + default: return 251; } @@ -3852,7 +3868,7 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu case EN_MINORLOSS: if (Link[index].Type != PUMP) { - if (value <= 0.0) return 211; + if (value < 0.0) return 211; Link[index].Km = 0.02517 * value / SQR(Link[index].Diam) / SQR(Link[index].Diam); } diff --git a/src/hydraul.c b/src/hydraul.c index ad24f0e..e8e8434 100755 --- a/src/hydraul.c +++ b/src/hydraul.c @@ -298,16 +298,12 @@ int allocmatrix(Project *pr) hyd->P = (double *) calloc(net->Nlinks+1,sizeof(double)); hyd->Y = (double *) calloc(net->Nlinks+1,sizeof(double)); - hyd->DemandFlow = (double *) calloc(net->Nnodes + 1, sizeof(double)); - hyd->EmitterFlow = (double *) calloc(net->Nnodes+1, sizeof(double)); hyd->Xflow = (double *) calloc(MAX((net->Nnodes+1), (net->Nlinks+1)), sizeof(double)); hyd->OldStatus = (StatusType *) calloc(net->Nlinks+net->Ntanks+1, sizeof(StatusType)); ERRCODE(MEMCHECK(hyd->P)); ERRCODE(MEMCHECK(hyd->Y)); - ERRCODE(MEMCHECK(hyd->DemandFlow)); - ERRCODE(MEMCHECK(hyd->EmitterFlow)); ERRCODE(MEMCHECK(hyd->Xflow)); ERRCODE(MEMCHECK(hyd->OldStatus)); return errcode; @@ -327,8 +323,6 @@ void freematrix(Project *pr) free(hyd->P); free(hyd->Y); - free(hyd->DemandFlow); - free(hyd->EmitterFlow); free(hyd->Xflow); free(hyd->OldStatus); } diff --git a/src/project.c b/src/project.c index 03f0d9a..8fb9a48 100644 --- a/src/project.c +++ b/src/project.c @@ -253,6 +253,8 @@ void initpointers(Project *pr) pr->hydraul.P = NULL; pr->hydraul.Y = NULL; pr->hydraul.Xflow = NULL; + pr->hydraul.DemandFlow = NULL; + pr->hydraul.EmitterFlow = NULL; pr->quality.NodeQual = NULL; pr->quality.PipeRateCoeff = NULL; @@ -313,10 +315,14 @@ int allocdata(Project *pr) pr->hydraul.NodeDemand = (double *)calloc(n, sizeof(double)); pr->hydraul.NodeHead = (double *)calloc(n, sizeof(double)); pr->quality.NodeQual = (double *)calloc(n, sizeof(double)); + pr->hydraul.DemandFlow = (double *)calloc(n, sizeof(double)); + pr->hydraul.EmitterFlow = (double *)calloc(n, sizeof(double)); ERRCODE(MEMCHECK(pr->network.Node)); ERRCODE(MEMCHECK(pr->hydraul.NodeDemand)); ERRCODE(MEMCHECK(pr->hydraul.NodeHead)); ERRCODE(MEMCHECK(pr->quality.NodeQual)); + ERRCODE(MEMCHECK(pr->hydraul.DemandFlow)); + ERRCODE(MEMCHECK(pr->hydraul.EmitterFlow)); } // Allocate memory for network links @@ -388,6 +394,8 @@ void freedata(Project *pr) free(pr->hydraul.LinkFlow); free(pr->hydraul.LinkSetting); free(pr->hydraul.LinkStatus); + free(pr->hydraul.DemandFlow); + free(pr->hydraul.EmitterFlow); free(pr->quality.NodeQual); // Free memory used for nodal adjacency lists diff --git a/src/smatrix.c b/src/smatrix.c index 67e1f53..95434f3 100755 --- a/src/smatrix.c +++ b/src/smatrix.c @@ -48,8 +48,8 @@ static int paralink(Network *, Smatrix *, int, int, int k); static void xparalinks(Network *); static int reordernodes(Project *); static int factorize(Project *); -static int growlist(Project *, int); -static int newlink(Project *, Padjlist); +static int growlist(Project *, int, int *); +static int newlink(Project *, Padjlist, int *); static int linked(Network *, int, int); static int addlink(Network *, int, int, int); static int storesparse(Project *, int); @@ -443,8 +443,8 @@ int factorize(Project *pr) Padjlist alink; // Find degree of each junction node - sm->Degree = (int *)calloc(net->Nnodes + 1, sizeof(int)); - if (sm->Degree == NULL) return 101; + int *degree = (int *)calloc(net->Nnodes + 1, sizeof(int)); + if (degree == NULL) return 101; // NOTE: For purposes of node re-ordering, Tanks (nodes with // indexes above Njuncs) have zero degree of adjacency. @@ -453,7 +453,7 @@ int factorize(Project *pr) { for (alink = net->Adjlist[k]; alink != NULL; alink = alink->next) { - if (alink->node > 0) sm->Degree[k]++; + if (alink->node > 0) degree[k]++; } } @@ -463,19 +463,19 @@ int factorize(Project *pr) for (k = 1; k <= net->Njuncs; k++) // Examine each junction { knode = sm->Order[k]; // Re-ordered index - if (!growlist(pr, knode)) // Augment adjacency list + if (!growlist(pr, knode, degree)) // Augment adjacency list { errcode = 101; break; } - sm->Degree[knode] = 0; // In-activate node + degree[knode] = 0; // In-activate node } - free(sm->Degree); + free(degree); return errcode; } -int growlist(Project *pr, int knode) +int growlist(Project *pr, int knode, int *degree) /* **-------------------------------------------------------------- ** Input: knode = node index @@ -496,10 +496,10 @@ int growlist(Project *pr, int knode) for (alink = net->Adjlist[knode]; alink != NULL; alink = alink -> next) { node = alink->node; // End node of connecting link - if (node > 0 && sm->Degree[node] > 0) // End node is active + if (node > 0 && degree[node] > 0) // End node is active { - sm->Degree[node]--; // Reduce degree of adjacency - if (!newlink(pr, alink)) // Add to adjacency list + degree[node]--; // Reduce degree of adjacency + if (!newlink(pr, alink, degree)) // Add to adjacency list { return 0; } @@ -509,7 +509,7 @@ int growlist(Project *pr, int knode) } -int newlink(Project *pr, Padjlist alink) +int newlink(Project *pr, Padjlist alink, int *degree) /* **-------------------------------------------------------------- ** Input: alink = element of node's adjacency list @@ -533,7 +533,7 @@ int newlink(Project *pr, Padjlist alink) // If jnode still active, and inode not connected to jnode, // then add a new connection between inode and jnode. - if (jnode > 0 && sm->Degree[jnode] > 0) // jnode still active + if (jnode > 0 && degree[jnode] > 0) // jnode still active { if (!linked(net, inode, jnode)) // inode not linked to jnode { @@ -545,8 +545,8 @@ int newlink(Project *pr, Padjlist alink) // reflect the new connection. if (!addlink(net, inode, jnode, sm->Ncoeffs)) return 0; if (!addlink(net, jnode, inode, sm->Ncoeffs)) return 0; - sm->Degree[inode]++; - sm->Degree[jnode]++; + degree[inode]++; + degree[jnode]++; } } } diff --git a/src/types.h b/src/types.h index 713adc2..50dc50a 100755 --- a/src/types.h +++ b/src/types.h @@ -688,7 +688,6 @@ typedef struct { *XLNZ, // Start position of each column in NZSUB *NZSUB, // Row index of each coeff. in each column *LNZ, // Position of each coeff. in Aij array - *Degree, // Number of links adjacent to each node *link, // Array used by linear eqn. solver *first; // Array used by linear eqn. solver