diff --git a/src/epanet.c b/src/epanet.c index 8942f6e..82f44ea 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -11,12 +11,16 @@ ****************************************************************************** */ -#include -#include -#include -#ifndef __APPLE__ -#include +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include #endif +#include +#include + #include #include @@ -279,7 +283,7 @@ int DLLEXPORT EN_getcomment(EN_Project p, int object, int index, char *comment) /*---------------------------------------------------------------- ** Input: object = a type of object (see EN_ObjectType) ** index = the object's index -** Output: comment = the object's descriptive comment +** Output: comment = the object's descriptive comment ** Returns: error code ** Purpose: Retrieves an object's descriptive comment **---------------------------------------------------------------- @@ -840,7 +844,7 @@ int DLLEXPORT EN_closeQ(EN_Project p) if (!p->Openflag) return 102; closequal(p); p->quality.OpenQflag = FALSE; - closeoutfile(p); + closeoutfile(p); return 0; } @@ -1637,7 +1641,7 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, char *chemName, p->network.Node[i].C0 *= Ucf[QUALITY]; } } - + Ucf[QUALITY] = ccf; Ucf[LINKQUAL] = ccf; Ucf[REACTRATE] = ccf; diff --git a/src/epanet2.c b/src/epanet2.c index 6ebb278..2490c64 100644 --- a/src/epanet2.c +++ b/src/epanet2.c @@ -10,10 +10,12 @@ Last Updated: 03/17/2019 ****************************************************************************** */ -#ifndef __APPLE__ -#include +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include #else -#include + #include #endif #include diff --git a/src/epanet_py.c b/src/epanet_py.c index b1b315d..6cc3302 100644 --- a/src/epanet_py.c +++ b/src/epanet_py.c @@ -11,8 +11,13 @@ ****************************************************************************** */ - -#include +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include +#endif #include #include "epanet_py.h" diff --git a/src/hash.c b/src/hash.c index 95ac8dd..5e8e7cd 100755 --- a/src/hash.c +++ b/src/hash.c @@ -11,11 +11,13 @@ ****************************************************************************** */ -#ifndef __APPLE__ -#include -#else -#include -#endif + #ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include + #else + #include + #endif #include #include "hash.h" @@ -84,7 +86,7 @@ int hashtable_update(HashTable *ht, char *key, int new_data) { unsigned int i = gethash(key); DataEntry *entry; - + if ( i >= HASHTABLEMAXSIZE ) return NOTFOUND; entry = ht[i]; while (entry != NULL) @@ -104,7 +106,7 @@ int hashtable_delete(HashTable *ht, char *key) { unsigned int i = gethash(key); DataEntry *entry, *preventry; - + if ( i >= HASHTABLEMAXSIZE ) return NOTFOUND; preventry = NULL; @@ -164,7 +166,7 @@ void hashtable_free(HashTable *ht) { DataEntry *entry, *nextentry; int i; - + for (i = 0; i < HASHTABLEMAXSIZE; i++) { entry = ht[i]; diff --git a/src/hydcoeffs.c b/src/hydcoeffs.c index b6c002c..69785d8 100644 --- a/src/hydcoeffs.c +++ b/src/hydcoeffs.c @@ -11,13 +11,16 @@ ****************************************************************************** */ +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include +#endif #include #include -#ifndef __APPLE__ -#include -#else -#include -#endif + #include #include "types.h" @@ -85,12 +88,12 @@ void resistcoeff(Project *pr, int k) double e, d, L; Slink *link = &net->Link[k]; - + link->Qa = 0.0; switch (link->Type) { // ... Link is a pipe. Compute resistance based on headloss formula. - // Friction factor for D-W formula gets included during head loss + // Friction factor for D-W formula gets included during head loss // calculation. case CVPIPE: case PIPE: @@ -244,14 +247,14 @@ void linkcoeffs(Project *pr) // Update linear system coeffs. associated with start node n1 // ... node n1 is junction - if (n1 <= net->Njuncs) + if (n1 <= net->Njuncs) { sm->Aii[sm->Row[n1]] += hyd->P[k]; // Diagonal coeff. sm->F[sm->Row[n1]] += hyd->Y[k]; // RHS coeff. } // ... node n1 is a tank/reservoir - else sm->F[sm->Row[n2]] += (hyd->P[k] * hyd->NodeHead[n1]); + else sm->F[sm->Row[n2]] += (hyd->P[k] * hyd->NodeHead[n1]); // Update linear system coeffs. associated with end node n2 // ... node n2 is junction @@ -262,7 +265,7 @@ void linkcoeffs(Project *pr) } // ... node n2 is a tank/reservoir - else sm->F[sm->Row[n1]] += (hyd->P[k] * hyd->NodeHead[n2]); + else sm->F[sm->Row[n1]] += (hyd->P[k] * hyd->NodeHead[n2]); } } @@ -321,13 +324,13 @@ void valvecoeffs(Project *pr) // Coeffs. for fixed status valves have already been computed if (hyd->LinkSetting[k] == MISSING) continue; - // Start & end nodes of valve's link + // Start & end nodes of valve's link link = &net->Link[k]; n1 = link->N1; n2 = link->N2; // Call valve-specific function - switch (link->Type) + switch (link->Type) { case PRV: prvcoeff(pr, k, n1, n2); @@ -482,7 +485,7 @@ void demandcoeffs(Project *pr) double dp, // pressure range over which demand can vary (ft) n, // exponent in head loss v. demand function hloss, // head loss in supplying demand (ft) - hgrad; // gradient of demand head loss (ft/cfs) + hgrad; // gradient of demand head loss (ft/cfs) // Get demand function parameters if (hyd->DemandModel == DDA) return; @@ -659,12 +662,12 @@ void DWpipecoeff(Project *pr, int k) Slink *link = &pr->network.Link[k]; double q = ABS(hyd->LinkFlow[k]); - double r = link->R; // Resistance coeff. - double ml = link->Km; // Minor loss coeff. + double r = link->R; // Resistance coeff. + double ml = link->Km; // Minor loss coeff. double e = link->Kc / link->Diam; // Relative roughness double s = hyd->Viscos * link->Diam; // Viscosity / diameter double hloss, hgrad, f, dfdq, r1; - + // Compute head loss and its derivative // ... use Hagen-Poiseuille formula for laminar flow (Re <= 2000) if (q <= A2 * s) @@ -673,7 +676,7 @@ void DWpipecoeff(Project *pr, int k) hloss = hyd->LinkFlow[k] * (r + ml * q); hgrad = r + 2.0 * ml * q; } - + // ... otherwise use Darcy-Weisbach formula with friction factor else { @@ -683,7 +686,7 @@ void DWpipecoeff(Project *pr, int k) hloss = r1 * q * hyd->LinkFlow[k]; hgrad = (2.0 * r1 * q) + (dfdq * r * q * q); } - + // Compute P and Y coefficients hyd->P[k] = 1.0 / hgrad; hyd->Y[k] = hloss / hgrad; @@ -753,7 +756,7 @@ void pumpcoeff(Project *pr, int k) int p; // Pump index double h0, // Shutoff head - q, // Abs. value of flow + q, // Abs. value of flow r, // Flow resistance coeff. n, // Flow exponent coeff. setting, // Pump speed setting @@ -899,7 +902,7 @@ void gpvcoeff(Project *pr, int k) Hydraul *hyd = &pr->hydraul; // Treat as a pipe if valve closed - if (hyd->LinkStatus[k] == CLOSED) valvecoeff(pr, k); + if (hyd->LinkStatus[k] == CLOSED) valvecoeff(pr, k); // Otherwise utilize segment of head loss curve // bracketing current flow (curve index is stored @@ -939,7 +942,7 @@ void pbvcoeff(Project *pr, int 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); + valvecoeff(pr, k); } // If valve is active @@ -948,7 +951,7 @@ void pbvcoeff(Project *pr, int k) // Treat as a pipe if minor loss > valve setting if (link->Km * SQR(hyd->LinkFlow[k]) > hyd->LinkSetting[k]) { - valvecoeff(pr, k); + valvecoeff(pr, k); } // Otherwise force headloss across valve to be equal to setting else @@ -983,7 +986,7 @@ void tcvcoeff(Project *pr, int k) } // Then apply usual valve formula - valvecoeff(pr, k); + valvecoeff(pr, k); // Restore original loss coeff. link->Km = km; @@ -1017,7 +1020,7 @@ void prvcoeff(Project *pr, int k, int n1, int n2) { // Set coeffs. to force head at downstream - // node equal to valve setting & force flow + // node equal to valve setting & force flow // to equal to flow excess at downstream node. hyd->P[k] = 0.0; @@ -1069,7 +1072,7 @@ void psvcoeff(Project *pr, int k, int n1, int n2) if (hyd->LinkStatus[k] == ACTIVE) { // Set coeffs. to force head at upstream - // node equal to valve setting & force flow + // node equal to valve setting & force flow // equal to flow excess at upstream node. hyd->P[k] = 0.0; @@ -1138,7 +1141,7 @@ void fcvcoeff(Project *pr, int k, int n1, int n2) else { - valvecoeff(pr, k); + valvecoeff(pr, k); sm->Aij[sm->Ndx[k]] -= hyd->P[k]; sm->Aii[i] += hyd->P[k]; sm->Aii[j] += hyd->P[k]; @@ -1162,7 +1165,7 @@ void valvecoeff(Project *pr, int k) Slink *link = &pr->network.Link[k]; double flow, q, y, qa, hgrad; - + flow = hyd->LinkFlow[k]; // Valve is closed. Use a very small matrix coeff. diff --git a/src/hydraul.c b/src/hydraul.c index 703f7b7..1e3532e 100755 --- a/src/hydraul.c +++ b/src/hydraul.c @@ -3,7 +3,7 @@ Project: OWA EPANET Version: 2.2 Module: hydraul.c - Description: implements EPANET's hydraulic engine + Description: implements EPANET's hydraulic engine Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE @@ -11,13 +11,16 @@ ****************************************************************************** */ +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include +#endif #include #include -#ifndef __APPLE__ -#include -#else -#include -#endif + #include #include "types.h" @@ -48,9 +51,9 @@ void tanklevels(Project *, long); int openhyd(Project *pr) /* *-------------------------------------------------------------- - * Input: none - * Output: returns error code - * Purpose: opens hydraulics solver system + * Input: none + * Output: returns error code + * Purpose: opens hydraulics solver system *-------------------------------------------------------------- */ { @@ -92,8 +95,8 @@ void inithyd(Project *pr, int initflag) **-------------------------------------------------------------- ** Input: initflag > 0 if link flows should be re-initialized ** = 0 if not -** Output: none -** Purpose: initializes hydraulics solver system +** Output: none +** Purpose: initializes hydraulics solver system **-------------------------------------------------------------- */ { @@ -106,7 +109,7 @@ void inithyd(Project *pr, int initflag) Stank *tank; Slink *link; Spump *pump; - + // Initialize tanks for (i = 1; i <= net->Ntanks; i++) { @@ -128,7 +131,7 @@ void inithyd(Project *pr, int initflag) for (i = 1; i <= net->Nlinks; i++) { link = &net->Link[i]; - + // Initialize status and setting hyd->LinkStatus[i] = link->Status; hyd->LinkSetting[i] = link->Kc; @@ -140,7 +143,7 @@ void inithyd(Project *pr, int initflag) if ( (link->Type == PRV || link->Type == PSV || link->Type == FCV) && (link->Kc != MISSING) - ) hyd->LinkStatus[i] = ACTIVE; + ) hyd->LinkStatus[i] = ACTIVE; // Initialize flows if necessary if (hyd->LinkStatus[i] <= CLOSED) @@ -170,7 +173,7 @@ void inithyd(Project *pr, int initflag) // Re-position hydraulics file if (pr->outfile.Saveflag) - { + { fseek(out->HydFile,out->HydOffset,SEEK_SET); } @@ -185,10 +188,10 @@ void inithyd(Project *pr, int initflag) int runhyd(Project *pr, long *t) /* **-------------------------------------------------------------- -** Input: none +** Input: none ** Output: t = pointer to current time (in seconds) -** Returns: error code -** Purpose: solves network hydraulics in a single time period +** Returns: error code +** Purpose: solves network hydraulics in a single time period **-------------------------------------------------------------- */ { @@ -199,7 +202,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); @@ -212,7 +215,7 @@ int runhyd(Project *pr, long *t) { // Report new status & save results if (rpt->Statflag) writehydstat(pr,iter,relerr); - + // If system unbalanced and no extra trials // allowed, then activate the Haltflag if (relerr > hyd->Hacc && hyd->ExtraIter == -1) @@ -229,11 +232,11 @@ int runhyd(Project *pr, long *t) int nexthyd(Project *pr, long *tstep) /* **-------------------------------------------------------------- -** Input: none +** Input: none ** Output: tstep = pointer to time step (in seconds) -** Returns: error code +** Returns: error code ** Purpose: finds length of next time step & updates tank -** levels and rule-based contol actions +** levels and rule-based contol actions **-------------------------------------------------------------- */ { @@ -242,7 +245,7 @@ int nexthyd(Project *pr, long *tstep) long hydstep; // Actual time step int errcode = 0; // Error code - + // Save current results to hydraulics file and // force end of simulation if Haltflag is active if (pr->outfile.Saveflag) errcode = savehyd(pr, &time->Htime); @@ -277,14 +280,14 @@ int nexthyd(Project *pr, long *tstep) *tstep = hydstep; return errcode; } - + void closehyd(Project *pr) /* **-------------------------------------------------------------- -** Input: none -** Output: returns error code -** Purpose: closes hydraulics solver system +** Input: none +** Output: returns error code +** Purpose: closes hydraulics solver system **-------------------------------------------------------------- */ { @@ -296,9 +299,9 @@ void closehyd(Project *pr) int allocmatrix(Project *pr) /* **-------------------------------------------------------------- -** Input: none -** Output: returns error code -** Purpose: allocates memory used for solution matrix coeffs. +** Input: none +** Output: returns error code +** Purpose: allocates memory used for solution matrix coeffs. **-------------------------------------------------------------- */ { @@ -306,7 +309,7 @@ int allocmatrix(Project *pr) Hydraul *hyd = &pr->hydraul; int errcode = 0; - + 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)); @@ -328,14 +331,14 @@ int allocmatrix(Project *pr) void freematrix(Project *pr) /* **-------------------------------------------------------------- -** Input: none -** Output: none -** Purpose: frees memory used for solution matrix coeffs. +** Input: none +** Output: none +** Purpose: frees memory used for solution matrix coeffs. **-------------------------------------------------------------- */ { Hydraul *hyd = &pr->hydraul; - + free(hyd->P); free(hyd->Y); free(hyd->DemandFlow); @@ -351,7 +354,7 @@ void initlinkflow(Project *pr, int i, char s, double k) ** Input: i = link index ** s = link status ** k = link setting (i.e., pump speed) -** Output: none +** Output: none ** Purpose: sets initial flow in link to QZERO if link is closed, ** to design flow for a pump, or to flow at velocity of ** 1 fps for other links. @@ -362,7 +365,7 @@ void initlinkflow(Project *pr, int i, char s, double k) Network *n = &pr->network; Slink *link = &n->Link[i]; - + if (s == CLOSED) { hyd->LinkFlow[i] = QZERO; @@ -383,8 +386,8 @@ void setlinkflow(Project *pr, int k, double dh) **-------------------------------------------------------------- ** Input: k = link index ** dh = head loss across link -** Output: none -** Purpose: sets flow in link based on current headloss +** Output: none +** Purpose: sets flow in link based on current headloss **-------------------------------------------------------------- */ { @@ -396,7 +399,7 @@ void setlinkflow(Project *pr, int k, double dh) double x ,y; Slink *link = &net->Link[k]; Scurve *curve; - + switch (link->Type) { case CVPIPE: @@ -408,7 +411,7 @@ void setlinkflow(Project *pr, int k, double dh) y = sqrt(ABS(dh) / link->R / 1.32547); hyd->LinkFlow[k] = x * y; } - + // For Hazen-Williams or Manning formulas use inverse of formula else { @@ -416,16 +419,16 @@ void setlinkflow(Project *pr, int k, double dh) y = 1.0 / hyd->Hexp; hyd->LinkFlow[k] = pow(x, y); } - + // Change sign of flow to match sign of head loss if (dh < 0.0) hyd->LinkFlow[k] = -hyd->LinkFlow[k]; break; - + case PUMP: // Convert headloss to pump head gain dh = -dh; p = findpump(net, k); - + // For custom pump curve, interpolate from curve if (net->Pump[p].Ptype == CUSTOM) { @@ -435,7 +438,7 @@ void setlinkflow(Project *pr, int k, double dh) hyd->LinkFlow[k] = interp(curve->Npts, curve->Y, curve->X, dh) * hyd->LinkSetting[k] / pr->Ucf[FLOW]; } - + // Otherwise use inverse of power curve else { @@ -459,7 +462,7 @@ void setlinkstatus(Project *pr, int index, char value, StatusType *s, double *k ** s = pointer to link status ** k = pointer to link setting ** Output: none -** Purpose: sets link status to OPEN or CLOSED +** Purpose: sets link status to OPEN or CLOSED **---------------------------------------------------------------- */ { @@ -467,11 +470,11 @@ void setlinkstatus(Project *pr, int index, char value, StatusType *s, double *k Slink *link = &net->Link[index]; LinkType t = link->Type; - - // Status set to open + + // Status set to open if (value == 1) { - // Adjust link setting for pumps & valves + // Adjust link setting for pumps & valves if (t == PUMP) *k = 1.0; if (t > PUMP && t != GPV) *k = MISSING; @@ -479,7 +482,7 @@ void setlinkstatus(Project *pr, int index, char value, StatusType *s, double *k *s = OPEN; } - // Status set to closed + // Status set to closed else if (value == 0) { // Adjust link setting for pumps & valves @@ -509,7 +512,7 @@ void setlinksetting(Project *pr, int index, double value, StatusType *s, Slink *link = &net->Link[index]; LinkType t = link->Type; - + // For a pump, status is OPEN if speed > 0, CLOSED otherwise if (t == PUMP) { @@ -531,15 +534,15 @@ void setlinksetting(Project *pr, int index, double value, StatusType *s, if (*k == MISSING && *s <= CLOSED) *s = OPEN; *k = value; } -} +} void demands(Project *pr) /* **-------------------------------------------------------------------- -** Input: none -** Output: none -** Purpose: computes demands at nodes during current time period +** Input: none +** Output: none +** Purpose: computes demands at nodes during current time period **-------------------------------------------------------------------- */ { @@ -610,9 +613,9 @@ void demands(Project *pr) int controls(Project *pr) /* **--------------------------------------------------------------------- -** Input: none -** Output: number of links whose setting changes -** Purpose: implements simple controls based on time or tank levels +** Input: none +** Output: number of links whose setting changes +** Purpose: implements simple controls based on time or tank levels **--------------------------------------------------------------------- */ { @@ -626,7 +629,7 @@ int controls(Project *pr) double k1, k2; char s1, s2; Slink *link; - Scontrol *control; + Scontrol *control; // Examine each control statement setsum = 0; @@ -680,7 +683,7 @@ int controls(Project *pr) if (pr->report.Statflag) writecontrolaction(pr,k,i); setsum++; } - } + } } return setsum; } @@ -689,9 +692,9 @@ int controls(Project *pr) long timestep(Project *pr) /* **---------------------------------------------------------------- -** Input: none -** Output: returns time step until next change in hydraulics -** Purpose: computes time step to advance hydraulic simulation +** Input: none +** Output: returns time step until next change in hydraulics +** Purpose: computes time step to advance hydraulic simulation **---------------------------------------------------------------- */ { @@ -699,26 +702,26 @@ long timestep(Project *pr) Times *time = &pr->times; long n, t, tstep; - + // Normal time step is hydraulic time step tstep = time->Hstep; - + // Revise time step based on time until next demand period // (n = next pattern period, t = time till next period) n = ((time->Htime + time->Pstart) / time->Pstep) + 1; t = n * time->Pstep - time->Htime; if (t > 0 && t < tstep) tstep = t; - + // Revise time step based on time until next reporting period t = time->Rtime - time->Htime; if (t > 0 && t < tstep) tstep = t; - + // Revise time step based on smallest time to fill or drain a tank tanktimestep(pr, &tstep); - + // Revise time step based on smallest time to activate a control controltimestep(pr, &tstep); - + // Evaluate rule-based controls (which will also update tank levels) if (net->Nrules > 0) ruletimestep(pr, &tstep); else tanklevels(pr, tstep); @@ -729,10 +732,10 @@ long timestep(Project *pr) int tanktimestep(Project *pr, long *tstep) /* **----------------------------------------------------------------- -** Input: *tstep = current time step -** Output: *tstep = modified current time step +** Input: *tstep = current time step +** Output: *tstep = modified current time step ** Purpose: revises time step based on shortest time to fill or -** drain a tank +** drain a tank **----------------------------------------------------------------- */ { @@ -777,10 +780,10 @@ int tanktimestep(Project *pr, long *tstep) void controltimestep(Project *pr, long *tstep) /* **------------------------------------------------------------------ -** Input: *tstep = current time step -** Output: *tstep = modified current time step +** Input: *tstep = current time step +** Output: *tstep = modified current time step ** Purpose: revises time step based on shortest time to activate -** a simple control +** a simple control **------------------------------------------------------------------ */ { @@ -792,24 +795,24 @@ void controltimestep(Project *pr, long *tstep) long t, t1, t2; Slink *link; Scontrol *control; - + // Examine each control for (i = 1; i <= net->Ncontrols; i++) { t = 0; control = &net->Control[i]; - // Control depends on a tank level + // Control depends on a tank level if ( (n = control->Node) > 0) { // Skip node if not a tank or reservoir if ((j = n - net->Njuncs) <= 0) continue; - + // Find current head and flow into tank h = hyd->NodeHead[n]; q = hyd->NodeDemand[n]; if (ABS(q) <= QZERO) continue; - + // Find time to reach upper or lower control level if ( (h < control->Grade && control->Type == HILEVEL && q > 0.0) || (h > control->Grade && control->Type == LOWLEVEL && q < 0.0) ) @@ -821,7 +824,7 @@ void controltimestep(Project *pr, long *tstep) // Control is based on elapsed time if (control->Type == TIMER) - { + { if (control->Time > pr->times.Htime) { t = control->Time - pr->times.Htime; @@ -853,16 +856,16 @@ void controltimestep(Project *pr, long *tstep) void ruletimestep(Project *pr, long *tstep) /* **-------------------------------------------------------------- -** Input: *tstep = current time step (sec) -** Output: *tstep = modified time step +** Input: *tstep = current time step (sec) +** Output: *tstep = modified time step ** Purpose: updates next time step by checking if any rules -** will fire before then; also updates tank levels. +** will fire before then; also updates tank levels. **-------------------------------------------------------------- */ { Network *net = &pr->network; Times *time = &pr->times; - + long tnow, // Start of time interval for rule evaluation tmax, // End of time interval for rule evaluation dt, // Normal time increment for rule evaluation @@ -880,7 +883,7 @@ void ruletimestep(Project *pr, long *tstep) } // Otherwise, time increment equals rule evaluation time step and - // first actual increment equals time until next even multiple of + // first actual increment equals time until next even multiple of // Rulestep occurs. else { @@ -888,7 +891,7 @@ void ruletimestep(Project *pr, long *tstep) dt1 = time->Rulestep - (tnow % time->Rulestep); } - // Make sure time increment is no larger than current time step + // Make sure time increment is no larger than current time step dt = MIN(dt, *tstep); dt1 = MIN(dt1, *tstep); if (dt1 == 0) dt1 = dt; @@ -918,14 +921,14 @@ void ruletimestep(Project *pr, long *tstep) *tstep = time->Htime - tnow; time->Htime = tnow; } - + void addenergy(Project *pr, long hstep) /* **------------------------------------------------------------- -** Input: hstep = time step (sec) -** Output: none -** Purpose: accumulates pump energy usage +** Input: hstep = time step (sec) +** Output: none +** Purpose: accumulates pump energy usage **------------------------------------------------------------- */ { @@ -1003,10 +1006,10 @@ void addenergy(Project *pr, long hstep) void getenergy(Project *pr, int k, double *kw, double *eff) /* **---------------------------------------------------------------- -** Input: k = link index +** Input: k = link index ** Output: *kw = kwatt energy used ** *eff = efficiency (pumps only) -** Purpose: computes flow energy associated with link k +** Purpose: computes flow energy associated with link k **---------------------------------------------------------------- */ { @@ -1022,7 +1025,7 @@ void getenergy(Project *pr, int k, double *kw, double *eff) double speed; // current speed setting Scurve *curve; Slink *link = &net->Link[k]; - + // No energy if link is closed if (hyd->LinkStatus[k] <= CLOSED) { @@ -1065,10 +1068,10 @@ void getenergy(Project *pr, int k, double *kw, double *eff) void tanklevels(Project *pr, long tstep) /* **---------------------------------------------------------------- -** Input: tstep = current time step -** Output: none -** Purpose: computes new water levels in tanks after current -** time step +** Input: tstep = current time step +** Output: none +** Purpose: computes new water levels in tanks after current +** time step **---------------------------------------------------------------- */ { @@ -1077,17 +1080,17 @@ void tanklevels(Project *pr, long tstep) int i, n; double dv; - + for (i = 1; i <= net->Ntanks; i++) { Stank *tank = &net->Tank[i]; if (tank->A == 0.0) continue; // Skip reservoirs - - // Update the tank's volume & water elevation + + // Update the tank's volume & water elevation n = tank->Node; dv = hyd->NodeDemand[n] * tstep; tank->V += dv; - + // Check if tank full/empty within next second if (tank->V + hyd->NodeDemand[n] >= tank->Vmax) { @@ -1105,10 +1108,10 @@ void tanklevels(Project *pr, long tstep) double tankvolume(Project *pr, int i, double h) /* **-------------------------------------------------------------------- -** Input: i = tank index -** h = water elevation in tank -** Output: returns water volume in tank -** Purpose: finds water volume in tank i corresponding to elev. h. +** Input: i = tank index +** h = water elevation in tank +** Output: returns water volume in tank +** Purpose: finds water volume in tank i corresponding to elev. h. **-------------------------------------------------------------------- */ { @@ -1122,7 +1125,7 @@ double tankvolume(Project *pr, int i, double h) // Use level*area if no volume curve j = tank->Vcurve; if (j == 0) return(tank->Vmin + (h - tank->Hmin) * tank->A); - + // If curve exists, interpolate on h to find volume v // remembering that volume curve is in original units. else @@ -1138,10 +1141,10 @@ double tankvolume(Project *pr, int i, double h) double tankgrade(Project *pr, int i, double v) /* **------------------------------------------------------------------- -** Input: i = tank index -** v = volume in tank -** Output: returns water level in tank -** Purpose: finds water level in tank i corresponding to volume v. +** Input: i = tank index +** v = volume in tank +** Output: returns water level in tank +** Purpose: finds water level in tank i corresponding to volume v. **------------------------------------------------------------------- */ { @@ -1154,7 +1157,7 @@ double tankgrade(Project *pr, int i, double v) // Use area if no volume curve j = tank->Vcurve; if (j == 0) return(tank->Hmin + (v - tank->Vmin) / tank->A); - + // If curve exists, interpolate on volume (originally the Y-variable // but used here as the X-variable) to find new level above bottom. // Remember that volume curve is stored in original units. diff --git a/src/hydsolver.c b/src/hydsolver.c index 3c0694a..0b0da25 100644 --- a/src/hydsolver.c +++ b/src/hydsolver.c @@ -12,13 +12,16 @@ ****************************************************************************** */ +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include +#endif #include #include -#ifndef __APPLE__ -#include -#else -#include -#endif + #include #include "types.h" @@ -453,7 +456,7 @@ void newlinkflows(Project *pr, Hydbalance *hbal, double *qsum, double *dqsum) hbal->maxflownode = -1; } - // Update net flows to fixed grade nodes + // Update net flows to fixed grade nodes if (hyd->LinkStatus[k] > CLOSED) { if (n1 > net->Njuncs) hyd->NodeDemand[n1] -= hyd->LinkFlow[k]; @@ -487,7 +490,7 @@ void newemitterflows(Project *pr, Hydbalance *hbal, double *qsum, // Skip junction if it does not have an emitter if (net->Node[i].Ke == 0.0) continue; - // Find emitter head loss and gradient + // Find emitter head loss and gradient emitheadloss(pr, i, &hloss, &hgrad); // Find emitter flow change diff --git a/src/hydstatus.c b/src/hydstatus.c index f7edb6b..2a4d20e 100644 --- a/src/hydstatus.c +++ b/src/hydstatus.c @@ -10,8 +10,15 @@ License: see LICENSE Last Updated: 11/27/2018 ****************************************************************************** */ - +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include +#endif #include + #include "types.h" #include "funcs.h" @@ -48,7 +55,7 @@ int valvestatus(Project *pr) n1, n2; // Start & end nodes double hset; // Valve head setting StatusType status; // Valve status settings - Slink *link; + Slink *link; // Examine each valve for (i = 1; i <= net->Nvalves; i++) @@ -59,7 +66,7 @@ int valvestatus(Project *pr) // Ignore valve if its status is fixed to OPEN/CLOSED if (hyd->LinkSetting[k] == MISSING) continue; - + // Get start/end node indexes & save current status n1 = link->N1; n2 = link->N2; @@ -449,7 +456,7 @@ void tankstatus(Project *pr, int k, int n1, int n2) // Case 2: Downstream head > tank head // (e.g., an open outflow check valve would close) - else if (cvstatus(pr, OPEN, h, q) == CLOSED) + else if (cvstatus(pr, OPEN, h, q) == CLOSED) { hyd->LinkStatus[k] = TEMPCLOSED; } diff --git a/src/inpfile.c b/src/inpfile.c index 8aa3c52..f09eb2e 100644 --- a/src/inpfile.c +++ b/src/inpfile.c @@ -11,13 +11,16 @@ Last Updated: 04/02/2019 ****************************************************************************** */ +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include +#endif #include #include -#ifndef __APPLE__ -#include -#else -#include -#endif + #include #include "types.h" @@ -38,7 +41,7 @@ extern char *TstatTxt[]; extern char *RptFlagTxt[]; extern char *SectTxt[]; -void saveauxdata(Project *pr, FILE *f) +void saveauxdata(Project *pr, FILE *f) /* ------------------------------------------------------------ Writes auxilary data from original input file to new file. @@ -51,7 +54,7 @@ void saveauxdata(Project *pr, FILE *f) char line[MAXLINE + 1]; char s[MAXLINE + 1]; FILE *InFile = pr->parser.InFile; - + // Re-open the input file if (InFile == NULL) { @@ -88,7 +91,7 @@ void saveauxdata(Project *pr, FILE *f) } } } - + // Write line of auxilary data to file else { @@ -147,7 +150,7 @@ int saveinpfile(Project *pr, const char *fname) // Open the new text file if ((f = fopen(fname, "wt")) == NULL) return 302; - // Write [TITLE] section + // Write [TITLE] section fprintf(f, s_TITLE); for (i = 0; i < 3; i++) { @@ -205,7 +208,7 @@ int saveinpfile(Project *pr, const char *fname) } } - // Write [PIPES] section + // Write [PIPES] section fprintf(f, "\n\n"); fprintf(f, s_PIPES); for (i = 1; i <= net->Nlinks; i++) @@ -244,7 +247,7 @@ int saveinpfile(Project *pr, const char *fname) // Pump has constant power if (pump->Ptype == CONST_HP) sprintf(s1, " POWER %.4f", link->Km); - // Pump has a head curve + // Pump has a head curve else if ((j = pump->Hcurve) > 0) { sprintf(s1, " HEAD %s", net->Curve[j].ID); @@ -539,7 +542,7 @@ int saveinpfile(Project *pr, const char *fname) fprintf(f, "\n ORDER TANK %-.2f", qual->TankOrder); fprintf(f, "\n GLOBAL BULK %-.6f", qual->Kbulk * SECperDAY); fprintf(f, "\n GLOBAL WALL %-.6f", qual->Kwall * SECperDAY); - + if (qual->Climit > 0.0) { fprintf(f, "\n LIMITING POTENTIAL %-.6f", qual->Climit * pr->Ucf[QUALITY]); @@ -548,7 +551,7 @@ int saveinpfile(Project *pr, const char *fname) { fprintf(f, "\n ROUGHNESS CORRELATION %-.6f", qual->Rfactor); } - + // Pipe-specific parameters for (i = 1; i <= net->Nlinks; i++) { diff --git a/src/input1.c b/src/input1.c index fe606d9..694d3f6 100644 --- a/src/input1.c +++ b/src/input1.c @@ -3,7 +3,7 @@ Project: OWA EPANET Version: 2.2 Module: input1.c -Description: retrieves network data from an EPANET input file +Description: retrieves network data from an EPANET input file Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE @@ -11,18 +11,23 @@ Last Updated: 03/17/2019 ****************************************************************************** */ -#include -#include -#include -#ifndef __APPLE__ -#include +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include #endif +#include +#include + +#include #include "types.h" #include "funcs.h" #include "hash.h" #include "text.h" -#include + // Default values #define MAXITER 200 // Default max. # hydraulic iterations @@ -56,7 +61,7 @@ int getdata(Project *pr) int errcode = 0; // Assign default data values & reporting options - setdefaults(pr); + setdefaults(pr); initreport(&pr->report); // Read in network data @@ -102,7 +107,7 @@ void setdefaults(Project *pr) parser->Pressflag = PSI; // Pressure units are psi out->Hydflag = SCRATCH; // No external hydraulics file rpt->Tstatflag = SERIES; // Generate time series output - + hyd->Formflag = HW; // Use Hazen-Williams formula hyd->Htol = HTOL; // Default head tolerance hyd->Qtol = QTOL; // Default flow tolerance @@ -353,7 +358,7 @@ int inittanks(Project *pr) */ { Network *net = &pr->network; - + int i, j, n = 0; double a; int errcode = 0, levelerr; @@ -546,7 +551,7 @@ void convertunits(Project *pr) Slink *link; Spump *pump; Scontrol *control; - + // Convert nodal elevations & initial WQ // (WQ source units are converted in QUALITY.C for (i = 1; i <= net->Nnodes; i++) @@ -644,7 +649,7 @@ void convertunits(Project *pr) pump->H0 /= pr->Ucf[HEAD]; pump->R *= (pow(pr->Ucf[FLOW], pump->N) / pr->Ucf[HEAD]); } - + // Convert flow range & max. head units pump->Q0 /= pr->Ucf[FLOW]; pump->Qmax /= pr->Ucf[FLOW]; @@ -653,7 +658,7 @@ void convertunits(Project *pr) } else { - // For flow control valves, convert flow setting + // For flow control valves, convert flow setting // while for other valves convert pressure setting link->Diam /= pr->Ucf[DIAM]; link->Km = 0.02517 * link->Km / SQR(link->Diam) / SQR(link->Diam); diff --git a/src/input2.c b/src/input2.c index f1d0c9f..f7af31d 100644 --- a/src/input2.c +++ b/src/input2.c @@ -11,12 +11,16 @@ Last Updated: 04/02/2019 ****************************************************************************** */ -#include -#include -#include -#ifndef __APPLE__ -#include +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include #endif +#include +#include + #include #include "types.h" @@ -56,7 +60,7 @@ int netsize(Project *pr) */ { Parser *parser = &pr->parser; - + char line[MAXLINE + 1]; // Line from input data file char *tok; // First token of line int sect, newsect; // Input data sections @@ -246,10 +250,10 @@ int readdata(Project *pr) // Stop if reach end of file or max. error count if (errsum == MAXERRS) break; } - + // Check for errors if (errsum > 0) errcode = 200; - + // Check for unlinked nodes if (!errcode) errcode = unlinked(pr); @@ -397,7 +401,7 @@ int updatepumpparams(Project *pr, int pumpindex) curve->Type = PUMP_CURVE; npts = curve->Npts; - // Generic power function curve + // Generic power function curve if (npts == 1) { pump->Ptype = POWER_FUNC; @@ -407,7 +411,7 @@ int updatepumpparams(Project *pr, int pumpindex) q2 = 2.0 * q1; h2 = 0.0; } - + // 3 point curve with shutoff head else if (npts == 3 && curve->X[0] == 0.0) { @@ -418,7 +422,7 @@ int updatepumpparams(Project *pr, int pumpindex) q2 = curve->X[2]; h2 = curve->Y[2]; } - + // Custom pump curve else { @@ -431,7 +435,7 @@ int updatepumpparams(Project *pr, int pumpindex) 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) { @@ -461,7 +465,7 @@ int addnodeID(Network *net, int n, char *id) **-------------------------------------------------------------- */ { - if (findnode(net,id)) return 0; + if (findnode(net,id)) return 0; strncpy(net->Node[n].ID, id, MAXID); hashtable_insert(net->NodeHashTable, net->Node[n].ID, n); return 1; @@ -587,7 +591,7 @@ int unlinked(Project *pr) Network *net = &pr->network; int *marked; int i, err, errcode; - + errcode = 0; err = 0; @@ -596,19 +600,19 @@ int unlinked(Project *pr) ERRCODE(MEMCHECK(marked)); if (errcode) return errcode; memset(marked, 0, (net->Nnodes + 1) * sizeof(int)); - + // Mark end nodes of each link for (i = 1; i <= net->Nlinks; i++) { marked[net->Link[i].N1]++; marked[net->Link[i].N2]++; } - + // Check each junction for (i = 1; i <= net->Njuncs; i++) { // If not marked then error - if (marked[i] == 0) + if (marked[i] == 0) { err++; sprintf(pr->Msg, "Error 233: %s %s", geterrmsg(233, pr->Msg), net->Node[i].ID); @@ -638,7 +642,7 @@ int getpatterns(Project *pr) SFloatlist *f; STmplist *tmppattern; Spattern *pattern; - + // Start at head of the list of patterns tmppattern = parser->Patlist; @@ -696,7 +700,7 @@ int getcurves(Project *pr) { Network *net = &pr->network; Parser *parser = &pr->parser; - + int i, j; double x; char errmsg[MAXMSG+1]; @@ -827,14 +831,14 @@ int gettokens(char *s, char** Tok, int maxToks, char *comment) int m, n; size_t len; char *c, *c2; - + // clear comment comment[0] = '\0'; - + // Begin with no tokens for (n=0; n 0 && n < MAXTOKS) { @@ -874,7 +878,7 @@ int gettokens(char *s, char** Tok, int maxToks, char *comment) { s++; // Start token after quote m = (int)strcspn(s,"\"\n\r"); // Find end quote (or EOL) - } + } s[m] = '\0'; // Null-terminate the token Tok[n] = s; // Save pointer to token n++; // Update token count @@ -882,7 +886,7 @@ int gettokens(char *s, char** Tok, int maxToks, char *comment) } } return n; -} +} double hour(char *time, char *units) /* @@ -920,7 +924,7 @@ double hour(char *time, char *units) if (match(units, w_DAYS)) return (y[0] * 24.0); } - // Convert hh:mm:ss format to decimal hours + // Convert hh:mm:ss format to decimal hours if (n > 1) y[0] = y[0] + y[1] / 60.0 + y[2] / 3600.0; // If am/pm attached then adjust hour accordingly @@ -939,7 +943,7 @@ double hour(char *time, char *units) else return (y[0] + 12.0); } return -1.0; -} +} int getfloat(char *s, double *y) /* @@ -985,14 +989,14 @@ void inperrmsg(Project *pr, int err, int sect, char *line) */ { Parser *parser = &pr->parser; - + char errStr[MAXMSG + 1] = ""; char tok[MAXMSG + 1]; // Get token associated with input error if (parser->ErrTok >= 0) strcpy(tok, parser->Tok[parser->ErrTok]); else strcpy(tok, ""); - + // write error message to report file sprintf(pr->Msg, "Error %d: %s %s in %s section:", err, geterrmsg(err, errStr), tok, SectTxt[sect]); diff --git a/src/input3.c b/src/input3.c index fb35da2..2a32179 100644 --- a/src/input3.c +++ b/src/input3.c @@ -11,12 +11,16 @@ Last Updated: 03/17/2019 ****************************************************************************** */ -#include -#include -#include -#ifndef __APPLE__ -#include +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include #endif +#include +#include + #include #include "types.h" diff --git a/src/mempool.c b/src/mempool.c index 55552ed..eb75e43 100755 --- a/src/mempool.c +++ b/src/mempool.c @@ -14,10 +14,14 @@ ****************************************************************************** */ -#include -#ifndef __APPLE__ -#include +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include #endif + #include "mempool.h" /* diff --git a/src/output.c b/src/output.c index fd92077..5082cbb 100644 --- a/src/output.c +++ b/src/output.c @@ -11,13 +11,16 @@ Last Updated: 11/27/2018 ****************************************************************************** */ +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include +#endif #include #include -#ifndef __APPLE__ -#include -#else -#include -#endif + #include #include "types.h" @@ -32,7 +35,7 @@ static int savetimestat(Project *, REAL4 *, HdrType); static int savenetreacts(Project *, double, double, double, double); static int saveepilog(Project *); -// Functions to write/read x[1] to x[n] to/from binary file +// Functions to write/read x[1] to x[n] to/from binary file size_t f_save(REAL4 *x, int n, FILE *file) { return fwrite(x + 1, sizeof(REAL4), n, file); @@ -79,7 +82,7 @@ int savenetdata(Project *pr) { // Write integer variables to outFile ibuf[0] = MAGICNUMBER; - ibuf[1] = 20012; // keep version at 2.00.12 so that GUI will run + ibuf[1] = 20012; // keep version at 2.00.12 so that GUI will run ibuf[2] = net->Nnodes; ibuf[3] = net->Ntanks; ibuf[4] = net->Nlinks; @@ -141,7 +144,7 @@ int savenetdata(Project *pr) x[i] = (REAL4)(net->Node[i].El * pr->Ucf[ELEV]); } f_save(x, net->Nnodes, outFile); - + // Save link lengths & diameters to outFile for (i = 1; i <= net->Nlinks; i++) { @@ -185,7 +188,7 @@ int savehyd(Project *pr, long *htime) int errcode = 0; REAL4 *x; FILE *HydFile = out->HydFile; - + x = (REAL4 *)calloc(MAX(net->Nnodes, net->Nlinks) + 1, sizeof(REAL4)); if (x == NULL) return 101; @@ -212,13 +215,13 @@ int savehyd(Project *pr, long *htime) fwrite(x + 1, sizeof(REAL4), net->Nlinks, HydFile); //f_save(x, net->Nlinks, HydFile); - // Save link status + // Save link status for (i = 1; i <= net->Nlinks; i++) x[i] = (REAL4)hyd->LinkStatus[i]; fwrite(x + 1, sizeof(REAL4), net->Nlinks, HydFile); //f_save(x, net->Nlinks, HydFile); - // Save link settings & check for successful write-to-disk - // (We assume that if any of the previous fwrites failed, + // Save link settings & check for successful write-to-disk + // (We assume that if any of the previous fwrites failed, // then this one will also fail.) for (i = 1; i <= net->Nlinks; i++) x[i] = (REAL4)hyd->LinkSetting[i]; if (fwrite(x + 1, sizeof(REAL4), net->Nlinks, HydFile) < @@ -354,7 +357,7 @@ int readhyd(Project *pr, long *hydtime) int result = 1; REAL4 *x; FILE *HydFile = out->HydFile; - + x = (REAL4 *)calloc(MAX(net->Nnodes, net->Nlinks) + 1, sizeof(REAL4)); if (x == NULL) return 0; @@ -473,7 +476,7 @@ int nodeoutput(Project *pr, int j, REAL4 *x, double ucf) } } - // Write x[1] to x[net->Nnodes] to output file + // Write x[1] to x[net->Nnodes] to output file if (f_save(x, net->Nnodes, outFile) < (unsigned)net->Nnodes) return 308; return 0; } @@ -497,7 +500,7 @@ int linkoutput(Project *pr, int j, REAL4 *x, double ucf) int i; double a, h, q, f, setting; FILE *outFile = out->TmpOutFile; - + // Load computed results (in proper units) into buffer x switch (j) { @@ -631,7 +634,7 @@ int savefinaloutput(Project *pr) int errcode = 0; REAL4 *x; FILE *outFile = out->OutFile; - + // Save time series statistic if computed if (rpt->Tstatflag != SERIES && out->TmpOutFile != NULL) { @@ -680,7 +683,7 @@ int savetimestat(Project *pr, REAL4 *x, HdrType objtype) long startbyte, skipbytes; float *stat1, *stat2, xx; FILE *outFile = out->OutFile; - + // Compute number of bytes in temp output file to skip over (skipbytes) // when moving from one time period to the next for a particular variable if (objtype == NODEHDR) @@ -722,11 +725,11 @@ int savetimestat(Project *pr, REAL4 *x, HdrType objtype) stat2[i] = MISSING; } - // Position temp output file at start of output + // Position temp output file at start of output fseek(out->TmpOutFile, startbyte + (j - n1) * n * sizeof(REAL4), SEEK_SET); - // Process each time period + // Process each time period for (p = 1; p <= rpt->Nperiods; p++) { // Get output results for time period & update stats @@ -751,7 +754,7 @@ int savetimestat(Project *pr, REAL4 *x, HdrType objtype) } } - // Advance file to next period + // Advance file to next period if (p < rpt->Nperiods) fseek(out->TmpOutFile, skipbytes, SEEK_CUR); } @@ -821,7 +824,7 @@ int savenetreacts(Project *pr, double wbulk, double wwall, double wtank, double double t; REAL4 w[4]; FILE *outFile = out->OutFile; - + if (time->Dur > 0) t = (double)time->Dur / 3600.; else t = 1.; w[0] = (REAL4)(wbulk / t); @@ -846,7 +849,7 @@ int saveepilog(Project *pr) int errcode = 0; INT4 i; FILE *outFile = out->OutFile; - + i = rpt->Nperiods; if (fwrite(&i, sizeof(INT4), 1, outFile) < 1) errcode = 308; i = pr->Warnflag; diff --git a/src/project.c b/src/project.c index 1e99817..a2e5654 100644 --- a/src/project.c +++ b/src/project.c @@ -11,7 +11,13 @@ ****************************************************************************** */ -#include +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include +#endif #include #include diff --git a/src/quality.c b/src/quality.c index de27f63..d46bd68 100644 --- a/src/quality.c +++ b/src/quality.c @@ -11,13 +11,16 @@ Last Updated: 11/27/2018 ****************************************************************************** */ +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include +#endif #include #include -#ifndef __APPLE__ -#include -#else -#include -#endif + #include #include "mempool.h" @@ -60,7 +63,7 @@ int openqual(Project *pr) int errcode = 0; int n; - + // Return if no quality analysis requested if (qual->Qualflag == NONE) return errcode; diff --git a/src/qualreact.c b/src/qualreact.c index 0805a21..8faf89b 100644 --- a/src/qualreact.c +++ b/src/qualreact.c @@ -11,6 +11,13 @@ Last Updated: 11/27/2018 ****************************************************************************** */ +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include +#endif #include #include #include "types.h" diff --git a/src/qualroute.c b/src/qualroute.c index 72bb66f..aa8e26a 100644 --- a/src/qualroute.c +++ b/src/qualroute.c @@ -11,13 +11,17 @@ Last Updated: 11/27/2018 ****************************************************************************** */ -#include -#ifndef __APPLE__ -#include +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include #else -#include + #include #endif +#include + #include + #include "mempool.h" #include "types.h" diff --git a/src/report.c b/src/report.c index 5605ffb..c35d73f 100644 --- a/src/report.c +++ b/src/report.c @@ -11,13 +11,15 @@ ****************************************************************************** */ +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include +#endif #include #include -#ifndef __APPLE__ -#include -#else -#include -#endif #ifdef _WIN32 #define snprintf _snprintf @@ -83,7 +85,7 @@ int copyreport(Project* pr, char *filename) FILE *tfile; int c; Report *rpt = &pr->report; - + // Check that project's report file exists if (rpt->RptFile == NULL) return 0; @@ -101,7 +103,7 @@ int copyreport(Project* pr, char *filename) while ((c = fgetc(rpt->RptFile)) != EOF) fputc(c, tfile); fclose(rpt->RptFile); } - + // Close destination file fclose(tfile); diff --git a/src/rules.c b/src/rules.c index 7e9945f..d0addb8 100644 --- a/src/rules.c +++ b/src/rules.c @@ -11,13 +11,15 @@ ****************************************************************************** */ +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include +#endif #include #include -#ifndef __APPLE__ -#include -#else -#include -#endif #include "types.h" #include "funcs.h" diff --git a/src/smatrix.c b/src/smatrix.c index 510bb3e..1b14794 100755 --- a/src/smatrix.c +++ b/src/smatrix.c @@ -18,13 +18,16 @@ linsolve() -- called from netsolve() in HYDRAUL.C */ +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include +#endif #include #include -#ifndef __APPLE__ -#include -#else -#include -#endif + #include #include diff --git a/tests/test_net_builder.cpp b/tests/test_net_builder.cpp index cb7bf16..577d0df 100644 --- a/tests/test_net_builder.cpp +++ b/tests/test_net_builder.cpp @@ -11,6 +11,14 @@ ****************************************************************************** */ +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#else + #include +#endif + #include #include "test_toolkit.hpp" @@ -37,7 +45,7 @@ struct FixtureInitClose { FixtureInitClose() { error = 0; ph = NULL; - + EN_createproject(&ph); EN_init(ph, DATA_PATH_RPT, DATA_PATH_OUT, EN_GPM, EN_HW); } @@ -53,359 +61,359 @@ struct FixtureInitClose { -//BOOST_AUTO_TEST_CASE(net_builder_I) -//{ -// int error = 0; -// int flag = 00; -// long t, tstep; -// int i, ind, Lindex, Nindex, Cindex; -// double h_orig, h_build, h_build_loaded; -// -// // first we load Net1.inp, run it and record the head in Tank 2 at the end of the simulation (h_orig) -// EN_Project ph = NULL; -// EN_createproject(&ph); -// -// std::string path_inp = std::string(DATA_PATH_NET1); -// 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(), path_out.c_str()); -// BOOST_REQUIRE(error == 0); -// -// error = EN_getnodeindex(ph, (char *)"2", &Nindex); -// BOOST_REQUIRE(error == 0); -// -// error = EN_openH(ph); -// BOOST_REQUIRE(error == 0); -// -// error = EN_initH(ph, flag); -// BOOST_REQUIRE(error == 0); -// -// do { -// error = EN_runH(ph, &t); -// BOOST_REQUIRE(error == 0); -// -// // this is the head at the end of the simulation after loading the original Net1.inp -// error = EN_getnodevalue(ph, Nindex, EN_HEAD, &h_orig); -// BOOST_REQUIRE(error == 0); -// -// error = EN_nextH(ph, &tstep); -// BOOST_REQUIRE(error == 0); -// -// } while (tstep > 0); -// -// error = EN_closeH(ph); -// BOOST_REQUIRE(error == 0); -// -// error = EN_close(ph); -// BOOST_REQUIRE(error == 0); -// -// EN_deleteproject(&ph); -//} - -// BOOST_FIXTURE_TEST_CASE(test_build_net1, FixtureInitClose) -// { -// int flag = 00; -// long t, tstep; -// int i, ind, Lindex, Nindex, Cindex; -// double h_build; -// -// // now we build Net1 from scratch... -// char juncs[9][10] = { "10", "11", "12", "13", "21", "22", "23", "31", "32" }; -// double e[9] = { 710, 710, 700, 695, 700, 695, 690, 700, 710 }; -// double d[9] = { 0, 150, 150, 100, 150, 200, 150, 100, 100 }; -// double X[9] = { 20, 30, 50, 70, 30, 50, 70, 30, 50 }; -// double Y[9] = { 70, 70, 70, 70, 40, 40, 40, 10, 10 }; -// double L[12] = { 10530, 5280, 5280, 5280, 5280, 5280, 200, 5280, 5280, 5280, 5280, 5280 }; -// double dia[12] = { 18, 14, 10, 10, 12, 6, 18, 10, 12, 8, 8, 6 }; -// double P[12] = { 1.0f, 1.2f, 1.4f, 1.6f, 1.4f, 1.2f, 1.0f, 0.8f, 0.6f, 0.4f, 0.6f, 0.8f }; -// -// error = EN_addpattern(ph, (char *)"pat1"); -// BOOST_REQUIRE(error == 0); -// error = EN_setpattern(ph, 1, P, 12); -// BOOST_REQUIRE(error == 0); -// error = EN_setoption(ph, EN_DEFDEMANDPAT, 1); -// BOOST_REQUIRE(error == 0); -// for (i = 0; i < 9; i++) -// { -// error = EN_addnode(ph, juncs[i], EN_JUNCTION); -// BOOST_REQUIRE(error == 0); -// error = EN_setnodevalue(ph, i + 1, EN_ELEVATION, e[i]); -// BOOST_REQUIRE(error == 0); -// error = EN_setnodevalue(ph, i + 1, EN_BASEDEMAND, d[i]); -// BOOST_REQUIRE(error == 0); -// error = EN_setcoord(ph, i + 1, X[i], Y[i]); -// BOOST_REQUIRE(error == 0); -// //error = EN_setdemandpattern(ph, i + 1, 1, 1); -// //BOOST_REQUIRE(error == 0); -// } -// error = EN_addnode(ph, (char *)"9", EN_RESERVOIR); -// BOOST_REQUIRE(error == 0); -// error = EN_setcoord(ph, 10, 10, 70); -// BOOST_REQUIRE(error == 0); -// error = EN_setnodevalue(ph, 10, EN_ELEVATION, 800); -// BOOST_REQUIRE(error == 0); -// -// error = EN_addnode(ph, (char *)"2", EN_TANK); -// BOOST_REQUIRE(error == 0); -// error = EN_setcoord(ph, 11, 50, 90); -// BOOST_REQUIRE(error == 0); -// error = EN_setnodevalue(ph, 11, EN_TANKDIAM, 50.5); -// BOOST_REQUIRE(error == 0); -// error = EN_setnodevalue(ph, 11, EN_ELEVATION, 850); -// BOOST_REQUIRE(error == 0); -// error = EN_setnodevalue(ph, 11, EN_MAXLEVEL, 150); -// BOOST_REQUIRE(error == 0); -// error = EN_setnodevalue(ph, 11, EN_TANKLEVEL, 120); -// BOOST_REQUIRE(error == 0); -// error = EN_setnodevalue(ph, 11, EN_MINLEVEL, 100); -// BOOST_REQUIRE(error == 0); -// error = EN_setnodevalue(ph, 11, EN_MIXFRACTION, 1); -// BOOST_REQUIRE(error == 0); -// -// error = EN_addlink(ph, (char *)"10", EN_PIPE, (char *)"10", (char *)"11"); -// BOOST_REQUIRE(error == 0); -// error = EN_addlink(ph, (char *)"11", EN_PIPE, (char *)"11", (char *)"12"); -// BOOST_REQUIRE(error == 0); -// error = EN_addlink(ph, (char *)"12", EN_PIPE, (char *)"12", (char *)"13"); -// BOOST_REQUIRE(error == 0); -// error = EN_addlink(ph, (char *)"21", EN_PIPE, (char *)"21", (char *)"22"); -// BOOST_REQUIRE(error == 0); -// error = EN_addlink(ph, (char *)"22", EN_PIPE, (char *)"22", (char *)"23"); -// BOOST_REQUIRE(error == 0); -// error = EN_addlink(ph, (char *)"31", EN_PIPE, (char *)"31", (char *)"32"); -// BOOST_REQUIRE(error == 0); -// error = EN_addlink(ph, (char *)"110", EN_PIPE, (char *)"2", (char *)"12"); -// BOOST_REQUIRE(error == 0); -// error = EN_addlink(ph, (char *)"111", EN_PIPE, (char *)"11", (char *)"21"); -// BOOST_REQUIRE(error == 0); -// error = EN_addlink(ph, (char *)"112", EN_PIPE, (char *)"12", (char *)"22"); -// BOOST_REQUIRE(error == 0); -// error = EN_addlink(ph, (char *)"113", EN_PIPE, (char *)"13", (char *)"23"); -// BOOST_REQUIRE(error == 0); -// error = EN_addlink(ph, (char *)"121", EN_PIPE, (char *)"21", (char *)"31"); -// BOOST_REQUIRE(error == 0); -// error = EN_addlink(ph, (char *)"122", EN_PIPE, (char *)"22", (char *)"32"); -// BOOST_REQUIRE(error == 0); -// for (i = 0; i < 12; i++) -// { -// error = EN_setlinkvalue(ph, i + 1, EN_LENGTH, L[i]); -// BOOST_REQUIRE(error == 0); -// error = EN_setlinkvalue(ph, i + 1, EN_DIAMETER, dia[i]); -// BOOST_REQUIRE(error == 0); -// } -// -// error = EN_addlink(ph, (char *)"9", EN_PUMP, (char *)"9", (char *)"10"); -// BOOST_REQUIRE(error == 0); -// error = EN_addcurve(ph, (char *)"1"); -// BOOST_REQUIRE(error == 0); -// error = EN_setcurvevalue(ph, 1, 1, 1500, 250); -// BOOST_REQUIRE(error == 0); -// error = EN_getlinkindex(ph, (char *)"9", &ind); -// BOOST_REQUIRE(error == 0); -// error = EN_setheadcurveindex(ph, ind, 1); -// BOOST_REQUIRE(error == 0); -// -// error = EN_settimeparam(ph, EN_DURATION, 24 * 3600); -// BOOST_REQUIRE(error == 0); -// error = EN_settimeparam(ph, EN_PATTERNSTEP, 2 * 3600); -// BOOST_REQUIRE(error == 0); -// -// error = EN_getlinkindex(ph, (char *)"9", &Lindex); -// BOOST_REQUIRE(error == 0); -// error = EN_getnodeindex(ph, (char *)"2", &Nindex); -// BOOST_REQUIRE(error == 0); -// -// // Add controls -// error = EN_addcontrol(ph, EN_LOWLEVEL, Lindex, 1, Nindex, 110, &Cindex); -// BOOST_REQUIRE(error == 0); -// error = EN_addcontrol(ph, EN_HILEVEL, Lindex, 0, Nindex, 140, &Cindex); -// BOOST_REQUIRE(error == 0); -// -// error = EN_openH(ph); -// BOOST_REQUIRE(error == 0); -// error = EN_initH(ph, 0); -// BOOST_REQUIRE(error == 0); -// do { -// error = EN_runH(ph, &t); -// BOOST_REQUIRE(error == 0); -// // this is the head at the end of the simulation after building the network *without* saving it to file -// error = EN_getnodevalue(ph, Nindex, EN_HEAD, &h_build); -// BOOST_REQUIRE(error == 0); -// error = EN_nextH(ph, &tstep); -// BOOST_REQUIRE(error == 0); -// } while (tstep > 0); -// error = EN_closeH(ph); -// BOOST_REQUIRE(error == 0); -// -// error = EN_saveinpfile(ph, "net_builder.inp"); -// BOOST_REQUIRE(error == 0); -// } -// -// BOOST_AUTO_TEST_CASE(test_open_net1, * boost::unit_test::depends_on("test_net_builder/test_build_net1")) +// BOOST_AUTO_TEST_CASE(net_builder_I) // { // int error = 0; // int flag = 00; // long t, tstep; -// int Nindex = -1; -// double h_orig = 0.0, h_build = 0.0, h_build_loaded = 0.0; -// +// int i, ind, Lindex, Nindex, Cindex; +// double h_orig, h_build, h_build_loaded; // +// // first we load Net1.inp, run it and record the head in Tank 2 at the end of the simulation (h_orig) // EN_Project ph = NULL; +// EN_createproject(&ph); // -// // now we load the netwok we just built and saved -// EN_createproject(&ph); -// error = EN_open(ph, "net_builder.inp", DATA_PATH_RPT, DATA_PATH_OUT); -// BOOST_REQUIRE(error == 0); +// std::string path_inp = std::string(DATA_PATH_NET1); +// 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(), path_out.c_str()); +// BOOST_REQUIRE(error == 0); // // error = EN_getnodeindex(ph, (char *)"2", &Nindex); // BOOST_REQUIRE(error == 0); // -// error = EN_openH(ph); -// BOOST_REQUIRE(error == 0); -// -// error = EN_initH(ph, flag); -// BOOST_REQUIRE(error == 0); -// -// do { -// error = EN_runH(ph, &t); -// BOOST_REQUIRE(error == 0); -// // this is the head at the end of the simulation after building the network and saving it to file -// error = EN_getnodevalue(ph, Nindex, EN_HEAD, &h_build_loaded); -// BOOST_REQUIRE(error == 0); -// error = EN_nextH(ph, &tstep); -// BOOST_REQUIRE(error == 0); -// -// } while (tstep > 0); -// -// error = EN_closeH(ph); -// BOOST_REQUIRE(error == 0); -// -// error = EN_close(ph); -// BOOST_REQUIRE(error == 0); -// -// EN_deleteproject(&ph); -// -// //--------------------------------------------------------------------- -// // if we got this far we can compare results -// -// // compare the original to the build & saved network -// // BOOST_CHECK(abs(h_orig - h_build_loaded) < 0.0001); -// -// // compare the original to the build without saving -// // BOOST_CHECK(abs(h_orig - h_build) < 0.0001); -// } -// -// -// BOOST_FIXTURE_TEST_CASE(test_save_net2, FixtureInitClose) -// { -// //char id[EN_MAXID+1]; -// double p1_1, p2_1; // p1_2, p2_2; -// double q1_1, q2_1; // q1_2, q2_2; -// -// // Build a network -// error = EN_addnode(ph, (char *)"N1", EN_JUNCTION); -// BOOST_REQUIRE(error == 0); -// error = EN_addnode(ph, (char *)"N2", EN_JUNCTION); -// BOOST_REQUIRE(error == 0); -// error = EN_addnode(ph, (char *)"N3", EN_RESERVOIR); -// BOOST_REQUIRE(error == 0); -// error = EN_addnode(ph, (char *)"N4", EN_TANK); -// BOOST_REQUIRE(error == 0); -// error = EN_addlink(ph, (char *)"L1", EN_PUMP, (char *)"N3", (char *)"N1"); -// BOOST_REQUIRE(error == 0); -// error = EN_addlink(ph, (char *)"L2", EN_PIPE, (char *)"N1", (char *)"N3"); -// BOOST_REQUIRE(error == 0); -// error = EN_addlink(ph, (char *)"L3", EN_PIPE, (char *)"N1", (char *)"N2"); -// BOOST_REQUIRE(error == 0); -// error = EN_addcurve(ph, (char *)"C1"); +// error = EN_openH(ph); // BOOST_REQUIRE(error == 0); // -// // Set network data using the new helper functions -// error = EN_setcurvevalue(ph, 1, 1, 1500, 250); -// BOOST_REQUIRE(error == 0); -// error = EN_setjuncdata(ph, 1, 700, 500, (char *)""); -// BOOST_REQUIRE(error == 0); -// error = EN_setjuncdata(ph, 2, 710, 500, (char *)""); -// BOOST_REQUIRE(error == 0); -// error = EN_setnodevalue(ph, 3, EN_ELEVATION, 800); -// BOOST_REQUIRE(error == 0); -// error = EN_settankdata(ph, 4, 850, 120, 100, 150, 50.5, 0, (char *)""); -// BOOST_REQUIRE(error == 0); -// error = EN_setlinkvalue(ph, 1, EN_PUMP_HCURVE, 1); -// BOOST_REQUIRE(error == 0); -// error = EN_setpipedata(ph, 2, 10560, 12, 100, 0); -// BOOST_REQUIRE(error == 0); -// error = EN_setpipedata(ph, 3, 5280, 14, 100, 0); +// error = EN_initH(ph, flag); // BOOST_REQUIRE(error == 0); // -// // Run hydraulics -// error = EN_solveH(ph); +// do { +// error = EN_runH(ph, &t); +// BOOST_REQUIRE(error == 0); +// +// // this is the head at the end of the simulation after loading the original Net1.inp +// error = EN_getnodevalue(ph, Nindex, EN_HEAD, &h_orig); +// BOOST_REQUIRE(error == 0); +// +// error = EN_nextH(ph, &tstep); +// BOOST_REQUIRE(error == 0); +// +// } while (tstep > 0); +// +// error = EN_closeH(ph); // BOOST_REQUIRE(error == 0); // -// // Save results -// error = EN_getnodevalue(ph, 1, EN_PRESSURE, &p1_1); -// BOOST_REQUIRE(error == 0); -// error = EN_getnodevalue(ph, 2, EN_PRESSURE, &p2_1); -// BOOST_REQUIRE(error == 0); -// error = EN_getlinkvalue(ph, 1, EN_FLOW, &q1_1); -// BOOST_REQUIRE(error == 0); -// error = EN_getlinkvalue(ph, 2, EN_FLOW, &q2_1); +// error = EN_close(ph); // BOOST_REQUIRE(error == 0); // -// // Save project -// error = EN_saveinpfile(ph, "netbuilder_test2.inp"); -// BOOST_REQUIRE(error == 0); -// } -// -// -// BOOST_AUTO_TEST_CASE(test_reopen_net2, *boost::unit_test::depends_on("test_net_builder/test_save_net2")) -// { -// int error, index; -// -// double p1_2, p2_2; -// double q1_2, q2_2; -// -// // Open the saved project file -// EN_Project ph = NULL; -// error = EN_createproject(&ph); -// BOOST_REQUIRE(error == 0); -// error = EN_open(ph, "netbuilder_test2.inp", DATA_PATH_RPT, DATA_PATH_OUT); -// BOOST_REQUIRE(error == 0); -// -// // Run hydraulics -// error = EN_solveH(ph); -// BOOST_REQUIRE(error == 0); -// -// // Save these new results -// error = EN_getnodevalue(ph, 1, EN_PRESSURE, &p1_2); -// BOOST_REQUIRE(error == 0); -// error = EN_getnodevalue(ph, 2, EN_PRESSURE, &p2_2); -// BOOST_REQUIRE(error == 0); -// error = EN_getlinkindex(ph, (char *)"L1", &index); -// BOOST_REQUIRE(error == 0); -// error = EN_getlinkvalue(ph, index, EN_FLOW, &q1_2); -// BOOST_REQUIRE(error == 0); -// error = EN_getlinkindex(ph, (char *)"L2", &index); -// BOOST_REQUIRE(error == 0); -// error = EN_getlinkvalue(ph, index, EN_FLOW, &q2_2); -// BOOST_REQUIRE(error == 0); -// -// // Display old & new results -// //cout << "\n Node N1 Pressure: " << p1_1 << " " << p1_2; -// //cout << "\n Node N2 Pressure: " << p2_1 << " " << p2_2; -// //cout << "\n Link L1 Flow: " << q1_1 << " " << q1_2; -// //cout << "\n Link L2 Flow: " << q2_1 << " " << q2_2; -// -// // Compare old & new results -// // BOOST_CHECK(abs(p1_1 - p1_2) < 1.e-5); -// // BOOST_CHECK(abs(q1_1 - q1_2) < 1.e-5); -// // BOOST_CHECK(abs(p2_1 - p2_2) < 1.e-5); -// // BOOST_CHECK(abs(q2_1 - q2_2) < 1.e-5); -// -// // Close project -// EN_close(ph); -// EN_deleteproject(&ph); +// EN_deleteproject(&ph); // } +BOOST_FIXTURE_TEST_CASE(test_build_net1, FixtureInitClose) +{ + int flag = 00; + long t, tstep; + int i, ind, Lindex, Nindex, Cindex; + double h_build; + + // now we build Net1 from scratch... + char juncs[9][10] = { "10", "11", "12", "13", "21", "22", "23", "31", "32" }; + double e[9] = { 710, 710, 700, 695, 700, 695, 690, 700, 710 }; + double d[9] = { 0, 150, 150, 100, 150, 200, 150, 100, 100 }; + double X[9] = { 20, 30, 50, 70, 30, 50, 70, 30, 50 }; + double Y[9] = { 70, 70, 70, 70, 40, 40, 40, 10, 10 }; + double L[12] = { 10530, 5280, 5280, 5280, 5280, 5280, 200, 5280, 5280, 5280, 5280, 5280 }; + double dia[12] = { 18, 14, 10, 10, 12, 6, 18, 10, 12, 8, 8, 6 }; + double P[12] = { 1.0f, 1.2f, 1.4f, 1.6f, 1.4f, 1.2f, 1.0f, 0.8f, 0.6f, 0.4f, 0.6f, 0.8f }; + + error = EN_addpattern(ph, (char *)"pat1"); + BOOST_REQUIRE(error == 0); + error = EN_setpattern(ph, 1, P, 12); + BOOST_REQUIRE(error == 0); + error = EN_setoption(ph, EN_DEFDEMANDPAT, 1); + BOOST_REQUIRE(error == 0); + for (i = 0; i < 9; i++) + { + error = EN_addnode(ph, juncs[i], EN_JUNCTION); + BOOST_REQUIRE(error == 0); + error = EN_setnodevalue(ph, i + 1, EN_ELEVATION, e[i]); + BOOST_REQUIRE(error == 0); + error = EN_setnodevalue(ph, i + 1, EN_BASEDEMAND, d[i]); + BOOST_REQUIRE(error == 0); + error = EN_setcoord(ph, i + 1, X[i], Y[i]); + BOOST_REQUIRE(error == 0); + //error = EN_setdemandpattern(ph, i + 1, 1, 1); + //BOOST_REQUIRE(error == 0); + } + error = EN_addnode(ph, (char *)"9", EN_RESERVOIR); + BOOST_REQUIRE(error == 0); + error = EN_setcoord(ph, 10, 10, 70); + BOOST_REQUIRE(error == 0); + error = EN_setnodevalue(ph, 10, EN_ELEVATION, 800); + BOOST_REQUIRE(error == 0); + + error = EN_addnode(ph, (char *)"2", EN_TANK); + BOOST_REQUIRE(error == 0); + error = EN_setcoord(ph, 11, 50, 90); + BOOST_REQUIRE(error == 0); + error = EN_setnodevalue(ph, 11, EN_TANKDIAM, 50.5); + BOOST_REQUIRE(error == 0); + error = EN_setnodevalue(ph, 11, EN_ELEVATION, 850); + BOOST_REQUIRE(error == 0); + error = EN_setnodevalue(ph, 11, EN_MAXLEVEL, 150); + BOOST_REQUIRE(error == 0); + error = EN_setnodevalue(ph, 11, EN_TANKLEVEL, 120); + BOOST_REQUIRE(error == 0); + error = EN_setnodevalue(ph, 11, EN_MINLEVEL, 100); + BOOST_REQUIRE(error == 0); + error = EN_setnodevalue(ph, 11, EN_MIXFRACTION, 1); + BOOST_REQUIRE(error == 0); + + error = EN_addlink(ph, (char *)"10", EN_PIPE, (char *)"10", (char *)"11"); + BOOST_REQUIRE(error == 0); + error = EN_addlink(ph, (char *)"11", EN_PIPE, (char *)"11", (char *)"12"); + BOOST_REQUIRE(error == 0); + error = EN_addlink(ph, (char *)"12", EN_PIPE, (char *)"12", (char *)"13"); + BOOST_REQUIRE(error == 0); + error = EN_addlink(ph, (char *)"21", EN_PIPE, (char *)"21", (char *)"22"); + BOOST_REQUIRE(error == 0); + error = EN_addlink(ph, (char *)"22", EN_PIPE, (char *)"22", (char *)"23"); + BOOST_REQUIRE(error == 0); + error = EN_addlink(ph, (char *)"31", EN_PIPE, (char *)"31", (char *)"32"); + BOOST_REQUIRE(error == 0); + error = EN_addlink(ph, (char *)"110", EN_PIPE, (char *)"2", (char *)"12"); + BOOST_REQUIRE(error == 0); + error = EN_addlink(ph, (char *)"111", EN_PIPE, (char *)"11", (char *)"21"); + BOOST_REQUIRE(error == 0); + error = EN_addlink(ph, (char *)"112", EN_PIPE, (char *)"12", (char *)"22"); + BOOST_REQUIRE(error == 0); + error = EN_addlink(ph, (char *)"113", EN_PIPE, (char *)"13", (char *)"23"); + BOOST_REQUIRE(error == 0); + error = EN_addlink(ph, (char *)"121", EN_PIPE, (char *)"21", (char *)"31"); + BOOST_REQUIRE(error == 0); + error = EN_addlink(ph, (char *)"122", EN_PIPE, (char *)"22", (char *)"32"); + BOOST_REQUIRE(error == 0); + for (i = 0; i < 12; i++) + { + error = EN_setlinkvalue(ph, i + 1, EN_LENGTH, L[i]); + BOOST_REQUIRE(error == 0); + error = EN_setlinkvalue(ph, i + 1, EN_DIAMETER, dia[i]); + BOOST_REQUIRE(error == 0); + } + + error = EN_addlink(ph, (char *)"9", EN_PUMP, (char *)"9", (char *)"10"); + BOOST_REQUIRE(error == 0); + error = EN_addcurve(ph, (char *)"1"); + BOOST_REQUIRE(error == 0); + error = EN_setcurvevalue(ph, 1, 1, 1500, 250); + BOOST_REQUIRE(error == 0); + error = EN_getlinkindex(ph, (char *)"9", &ind); + BOOST_REQUIRE(error == 0); + error = EN_setheadcurveindex(ph, ind, 1); + BOOST_REQUIRE(error == 0); + + error = EN_settimeparam(ph, EN_DURATION, 24 * 3600); + BOOST_REQUIRE(error == 0); + error = EN_settimeparam(ph, EN_PATTERNSTEP, 2 * 3600); + BOOST_REQUIRE(error == 0); + + error = EN_getlinkindex(ph, (char *)"9", &Lindex); + BOOST_REQUIRE(error == 0); + error = EN_getnodeindex(ph, (char *)"2", &Nindex); + BOOST_REQUIRE(error == 0); + + // Add controls + error = EN_addcontrol(ph, EN_LOWLEVEL, Lindex, 1, Nindex, 110, &Cindex); + BOOST_REQUIRE(error == 0); + error = EN_addcontrol(ph, EN_HILEVEL, Lindex, 0, Nindex, 140, &Cindex); + BOOST_REQUIRE(error == 0); + + error = EN_openH(ph); + BOOST_REQUIRE(error == 0); + error = EN_initH(ph, 0); + BOOST_REQUIRE(error == 0); + do { + error = EN_runH(ph, &t); + BOOST_REQUIRE(error == 0); + // this is the head at the end of the simulation after building the network *without* saving it to file + error = EN_getnodevalue(ph, Nindex, EN_HEAD, &h_build); + BOOST_REQUIRE(error == 0); + error = EN_nextH(ph, &tstep); + BOOST_REQUIRE(error == 0); + } while (tstep > 0); + error = EN_closeH(ph); + BOOST_REQUIRE(error == 0); + + error = EN_saveinpfile(ph, "net_builder.inp"); + BOOST_REQUIRE(error == 0); +} + +BOOST_AUTO_TEST_CASE(test_open_net1, * boost::unit_test::depends_on("test_net_builder/test_build_net1")) +{ + int error = 0; + int flag = 00; + long t, tstep; + int Nindex = -1; + double h_orig = 0.0, h_build = 0.0, h_build_loaded = 0.0; + + + EN_Project ph = NULL; + + // now we load the netwok we just built and saved + EN_createproject(&ph); + error = EN_open(ph, "net_builder.inp", DATA_PATH_RPT, DATA_PATH_OUT); + BOOST_REQUIRE(error == 0); + + error = EN_getnodeindex(ph, (char *)"2", &Nindex); + BOOST_REQUIRE(error == 0); + + error = EN_openH(ph); + BOOST_REQUIRE(error == 0); + + error = EN_initH(ph, flag); + BOOST_REQUIRE(error == 0); + + do { + error = EN_runH(ph, &t); + BOOST_REQUIRE(error == 0); + // this is the head at the end of the simulation after building the network and saving it to file + error = EN_getnodevalue(ph, Nindex, EN_HEAD, &h_build_loaded); + BOOST_REQUIRE(error == 0); + error = EN_nextH(ph, &tstep); + BOOST_REQUIRE(error == 0); + + } while (tstep > 0); + + error = EN_closeH(ph); + BOOST_REQUIRE(error == 0); + + error = EN_close(ph); + BOOST_REQUIRE(error == 0); + + EN_deleteproject(&ph); + + //--------------------------------------------------------------------- + // if we got this far we can compare results + + // compare the original to the build & saved network + // BOOST_CHECK(abs(h_orig - h_build_loaded) < 0.0001); + + // compare the original to the build without saving + // BOOST_CHECK(abs(h_orig - h_build) < 0.0001); +} + + +BOOST_FIXTURE_TEST_CASE(test_save_net2, FixtureInitClose) +{ + //char id[EN_MAXID+1]; + double p1_1, p2_1; // p1_2, p2_2; + double q1_1, q2_1; // q1_2, q2_2; + + // Build a network + error = EN_addnode(ph, (char *)"N1", EN_JUNCTION); + BOOST_REQUIRE(error == 0); + error = EN_addnode(ph, (char *)"N2", EN_JUNCTION); + BOOST_REQUIRE(error == 0); + error = EN_addnode(ph, (char *)"N3", EN_RESERVOIR); + BOOST_REQUIRE(error == 0); + error = EN_addnode(ph, (char *)"N4", EN_TANK); + BOOST_REQUIRE(error == 0); + error = EN_addlink(ph, (char *)"L1", EN_PUMP, (char *)"N3", (char *)"N1"); + BOOST_REQUIRE(error == 0); + error = EN_addlink(ph, (char *)"L2", EN_PIPE, (char *)"N1", (char *)"N3"); + BOOST_REQUIRE(error == 0); + error = EN_addlink(ph, (char *)"L3", EN_PIPE, (char *)"N1", (char *)"N2"); + BOOST_REQUIRE(error == 0); + error = EN_addcurve(ph, (char *)"C1"); + BOOST_REQUIRE(error == 0); + + // Set network data using the new helper functions + error = EN_setcurvevalue(ph, 1, 1, 1500, 250); + BOOST_REQUIRE(error == 0); + error = EN_setjuncdata(ph, 1, 700, 500, (char *)""); + BOOST_REQUIRE(error == 0); + error = EN_setjuncdata(ph, 2, 710, 500, (char *)""); + BOOST_REQUIRE(error == 0); + error = EN_setnodevalue(ph, 3, EN_ELEVATION, 800); + BOOST_REQUIRE(error == 0); + error = EN_settankdata(ph, 4, 850, 120, 100, 150, 50.5, 0, (char *)""); + BOOST_REQUIRE(error == 0); + error = EN_setlinkvalue(ph, 1, EN_PUMP_HCURVE, 1); + BOOST_REQUIRE(error == 0); + error = EN_setpipedata(ph, 2, 10560, 12, 100, 0); + BOOST_REQUIRE(error == 0); + error = EN_setpipedata(ph, 3, 5280, 14, 100, 0); + BOOST_REQUIRE(error == 0); + + // Run hydraulics + error = EN_solveH(ph); + BOOST_REQUIRE(error == 0); + + // Save results + error = EN_getnodevalue(ph, 1, EN_PRESSURE, &p1_1); + BOOST_REQUIRE(error == 0); + error = EN_getnodevalue(ph, 2, EN_PRESSURE, &p2_1); + BOOST_REQUIRE(error == 0); + error = EN_getlinkvalue(ph, 1, EN_FLOW, &q1_1); + BOOST_REQUIRE(error == 0); + error = EN_getlinkvalue(ph, 2, EN_FLOW, &q2_1); + BOOST_REQUIRE(error == 0); + + // Save project + error = EN_saveinpfile(ph, "netbuilder_test2.inp"); + BOOST_REQUIRE(error == 0); +} + + +BOOST_AUTO_TEST_CASE(test_reopen_net2, *boost::unit_test::depends_on("test_net_builder/test_save_net2")) +{ + int error, index; + + double p1_2, p2_2; + double q1_2, q2_2; + + // Open the saved project file + EN_Project ph = NULL; + error = EN_createproject(&ph); + BOOST_REQUIRE(error == 0); + error = EN_open(ph, "netbuilder_test2.inp", DATA_PATH_RPT, DATA_PATH_OUT); + BOOST_REQUIRE(error == 0); + + // Run hydraulics + error = EN_solveH(ph); + BOOST_REQUIRE(error == 0); + + // Save these new results + error = EN_getnodevalue(ph, 1, EN_PRESSURE, &p1_2); + BOOST_REQUIRE(error == 0); + error = EN_getnodevalue(ph, 2, EN_PRESSURE, &p2_2); + BOOST_REQUIRE(error == 0); + error = EN_getlinkindex(ph, (char *)"L1", &index); + BOOST_REQUIRE(error == 0); + error = EN_getlinkvalue(ph, index, EN_FLOW, &q1_2); + BOOST_REQUIRE(error == 0); + error = EN_getlinkindex(ph, (char *)"L2", &index); + BOOST_REQUIRE(error == 0); + error = EN_getlinkvalue(ph, index, EN_FLOW, &q2_2); + BOOST_REQUIRE(error == 0); + + // Display old & new results + //cout << "\n Node N1 Pressure: " << p1_1 << " " << p1_2; + //cout << "\n Node N2 Pressure: " << p2_1 << " " << p2_2; + //cout << "\n Link L1 Flow: " << q1_1 << " " << q1_2; + //cout << "\n Link L2 Flow: " << q2_1 << " " << q2_2; + + // Compare old & new results +// BOOST_CHECK(abs(p1_1 - p1_2) < 1.e-5); +// BOOST_CHECK(abs(q1_1 - q1_2) < 1.e-5); +// BOOST_CHECK(abs(p2_1 - p2_2) < 1.e-5); +// BOOST_CHECK(abs(q2_1 - q2_2) < 1.e-5); + + // Close project + EN_close(ph); + EN_deleteproject(&ph); +} + BOOST_AUTO_TEST_SUITE_END()