New features and bug fixes

This commit is contained in:
Michael Tryby
2014-05-05 18:07:03 -04:00
parent 993cfce8a4
commit 0cd38fd697
16 changed files with 718 additions and 368 deletions

View File

@@ -1,76 +1,57 @@
----------------------- -----------------------
Build 2.00.11 (8/15/07) Build 2.00.12 (2/25/08)
----------------------- -----------------------
Computational Engine Changes (epanet2.dll and epanet2d.exe): Computational Engine Changes (epanet2.dll and epanet2d.exe):
=============================================================================== ===============================================================================
CODE MODULES CHANGES CODE MODULES CHANGES
=============================================================================== ===============================================================================
All All variables previously declared as floats were re-defined as EPANET.C Temporary files are now written to the users's current working
doubles except for those used to write results to binary output INPUT1.C directory or to the designated Temporary Directory when running
files and those used as arguments in the toolkit functions. VARS.H the Windows GUI, thus avoiding file access problems for users
FUNCS.H who do not have administrative privileges on their machine.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
EPANET.C The symbols CLE (for command line executable) and SOL (for shared EPANET.C The following tank parameters were made available for retrieval
object library) were introduced in addition to the existing TOOLKIT.H using the Toolkit's ENgetnodevalue function: tank diameter,
symbol DLL (for dynamic linked library) to support conditional EPANET2.H minimum volume, index of the tank's volume curve, the initial,
compliation for shared object libraries on Unix/Linux. minimum, and maximum water levels, the fraction of a 2-compart-
ment tank devoted to the mixing zone, and the tank's bulk
reaction rate coefficient. These same parameters (with the
exception of the volume curve) were made modifiable using the
ENsetnodevalue function, as was the choice of mixing model.
See the Toolkit Help file for details.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
EPANET.C EN_INITVOLUME, EN_MIXMODEL and EN_MIXZONEVOL were added to the EPANET.C A new Toolkit function, ENaddpattern, was added that allows
EPANET2.H list of tank parameters that can be retrieved with TOOLKIT.C programmers to add a new time pattern to the network in any
TOOLKIT.H ENgetnodevalue. EPANET2.H custom code that they write.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
EPANET.C Missing code was added to the ENgetnodevalue function to return HYDRAUL.C A DAMPLIMIT parameter was added to control at what point during
a value for EN_SOURCEPAT when requested. INPUT1.C the hydraulic solution iterations status checks on PRVs and PSVs
INPUT3.C begin and subsequent flow changes are dampened.
REPORT.C
VARS.H
TEXT.H
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
EPANET.H The function declarations in these "include" files were modified HYDRAUL.C Demands for tanks (net inflows/outflows) were not always being
TOOLKIT.H to support conditional compliation for shared object libraries set to zero when the tank was full or empty which was causing
on Unix/Linux. problems in the water quality routing solutions.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
INPUT3.C The keyword "HEADLOSS" is no longer confused with "HEAD" when QUALITY.C The water quality functions for all of the tank mixing models
parsing reporting variable names in the [REPORT] section of the were modified so as to produce more robust results for cases
input file. where there is a significant amount of volume exchange over a
water quality time step.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
RULES.C The input values for a tank's FILLTIME or DRAINTIME in a rule EPANET.C A problem with the system not recognizing that water quality
premise are now correctly converted to seconds in the QUALITY.C reactions could begin after some initial period of time when
newpremise() function. VARS.H the Toolkit was used to modify reaction rate coefficients was
fixed.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
HYDRAUL.C During hydraulic balancing, status checks on control valves are INPFILE.C A problem with extraneous lines being written to the [REPORT]
now made only when the convergence error drops to less than a section of an EPANET input file created with the ENsaveinpfile
factor of 10 of the accuracy limit and a damping factor of 0.6 function was fixed. Also the number of decimal places for some
is applied to flow changes computed at each iteration beyond items written to the saved file, such as nodal demands, was
this point. increased.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
HYDRAUL.C The logic for determining the status of PRVs and PSVs was changed TYPES.H The code version was changed to 20012 and INT4 was explicitly
to produce more robust solutions, particularly for the case of defined as an "int" data type.
multi-stage regulator stations where there are two or more PRVs
connected in parallel.
-------------------------------------------------------------------------------
HYDRAUL.C The matrix coefficients for fully open control valves are now set
directly rather than by assuming the valve has a certain length
and friction factor.
-------------------------------------------------------------------------------
HYDRAUL.C Changes were made to how the P-coefficient for FCVs and the Y-
coefficient for GPVs are calculated.
-------------------------------------------------------------------------------
HYDRAUL.C An extraneous "if" statement was removed from the resistance()
function; the Y-coefficient value in gpvcoeff() was corrected;
the P-coefficient value in fcvcoeff() was corrected.
-------------------------------------------------------------------------------
QUALITY.C The memory pool used for water quality routing segments was given
the name SegPool and declared as a static global variable.
-------------------------------------------------------------------------------
QUALITY.C In the release() function, the upstream node quality is now mixed
together with that of the upstream pipe segment when the quality
difference between the two is less than the CTOL tolerance.
-------------------------------------------------------------------------------
INPFILE.C The ENsaveinpfile toolkit function now writes disabled reporting
variables to the [REPORT] section of the generated input file.
-------------------------------------------------------------------------------
INPFILE.C The appearance of an extraneous character at the end of the .INP
file produced by the toolkit function ENsaveinpfile was fixed.
-------------------------------------------------------------------------------
TYPES.H MAXID was increased to allow ID names to contain up to 31
HASH.C characters.
-------------------------------------------------------------------------------
TYPES.H The code version was changed to 20011.
=============================================================================== ===============================================================================

View File

@@ -48,7 +48,7 @@ Also included are the following header files:
The comments at the top of each file lists the date when the latest The comments at the top of each file lists the date when the latest
update was made, and these updates can be located in the code by update was made, and these updates can be located in the code by
searching for comments with the phrase "/*** Updated" or with the searching for comments with the phrase "/*** Updated" or with the
release number (e.g., 2.00.11) in them. release number (e.g., 2.00.12) in them.
Other useful documentation that can be consulted includes the EPANET Other useful documentation that can be consulted includes the EPANET
Programmers Toolkit Help file and the EPANET Version 2 Users Manual. Programmers Toolkit Help file and the EPANET Version 2 Users Manual.

View File

@@ -11,6 +11,7 @@ DATE: 5/30/00
11/19/01 11/19/01
6/24/02 6/24/02
8/15/07 (2.00.11) 8/15/07 (2.00.11)
2/14/08 (2.00.12)
AUTHOR: L. Rossman AUTHOR: L. Rossman
US EPA - NRMRL US EPA - NRMRL
@@ -114,18 +115,26 @@ execute function x and set the error code equal to its return value.
/*** Following lines are deprecated ***/ //(2.00.11 - LR) /*** Following lines are deprecated ***/ //(2.00.11 - LR)
//#ifdef DLL //#ifdef DLL
//#include <windows.h> //#include <windows.h>
//#include <float.h>
/*** Updated 9/7/00 ***/
#include <float.h>
//#endif //#endif
/*** Need to define WINDOWS to use the getTmpName function ***/ //(2.00.12 - LR)
// --- define WINDOWS
#undef WINDOWS
#ifdef _WIN32
#define WINDOWS
#endif
#ifdef __WIN32__
#define WINDOWS
#endif
/************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <malloc.h> #include <malloc.h>
#include <math.h> #include <math.h>
#include <float.h> //(2.00.12 - LR)
#include "hash.h" #include "hash.h"
#include "text.h" #include "text.h"
#include "types.h" #include "types.h"
@@ -135,7 +144,6 @@ execute function x and set the error code equal to its return value.
#include "vars.h" #include "vars.h"
#include "toolkit.h" #include "toolkit.h"
void (* viewprog) (char *); /* Pointer to progress viewing function */ void (* viewprog) (char *); /* Pointer to progress viewing function */
@@ -349,10 +357,21 @@ int DLLEXPORT ENclose()
{ {
if (Openflag) writetime(FMT105); if (Openflag) writetime(FMT105);
freedata(); freedata();
if (TmpOutFile != OutFile) //(2.00.12 - LR)
{ //(2.00.12 - LR)
if (TmpOutFile != NULL) fclose(TmpOutFile); //(2.00.12 - LR)
remove(TmpFname); //(2.00.12 - LR)
} //(2.00.12 - LR)
if (InFile != NULL) fclose(InFile); if (InFile != NULL) fclose(InFile);
if (RptFile != NULL) fclose(RptFile); if (RptFile != NULL) fclose(RptFile);
if (HydFile != NULL) fclose(HydFile); if (HydFile != NULL) fclose(HydFile);
if (OutFile != NULL) fclose(OutFile); if (OutFile != NULL) fclose(OutFile);
if (Hydflag == SCRATCH) remove(HydFname); //(2.00.12 - LR)
if (Outflag == SCRATCH) remove(OutFname); //(2.00.12 - LR)
Openflag = FALSE; Openflag = FALSE;
OpenHflag = FALSE; OpenHflag = FALSE;
SaveHflag = FALSE; SaveHflag = FALSE;
@@ -1403,6 +1422,59 @@ int DLLEXPORT ENgetnodevalue(int index, int code, float *value)
v = C[index]*Ucf[QUALITY]; v = C[index]*Ucf[QUALITY];
break; break;
/*** New parameters added for retrieval begins here ***/ //(2.00.12 - LR)
/*** (Thanks to Nicolas Basile of Ecole Polytechnique ***/
/*** de Montreal for suggesting some of these.) ***/
case EN_TANKDIAM:
v = 0.0;
if ( index > Njuncs )
{
v = 4.0/PI*sqrt(Tank[index-Njuncs].A)*Ucf[ELEV];
}
break;
case EN_MINVOLUME:
v = 0.0;
if ( index > Njuncs ) v = Tank[index-Njuncs].Vmin * Ucf[VOLUME];
break;
case EN_VOLCURVE:
v = 0.0;
if ( index > Njuncs ) v = Tank[index-Njuncs].Vcurve;
break;
case EN_MINLEVEL:
v = 0.0;
if ( index > Njuncs )
{
v = (Tank[index-Njuncs].Hmin - Node[index].El) * Ucf[ELEV];
}
break;
case EN_MAXLEVEL:
v = 0.0;
if ( index > Njuncs )
{
v = (Tank[index-Njuncs].Hmax - Node[index].El) * Ucf[ELEV];
}
break;
case EN_MIXFRACTION:
v = 1.0;
if ( index > Njuncs && Tank[index-Njuncs].Vmax > 0.0)
{
v = Tank[index-Njuncs].V1max / Tank[index-Njuncs].Vmax;
}
break;
case EN_TANK_KBULK:
v = 0.0;
if (index > Njuncs) v = Tank[index-Njuncs].Kb * SECperDAY;
break;
/*** New parameter additions ends here. ***/ //(2.00.12 - LR)
default: return(251); default: return(251);
} }
*value = (float)v; *value = (float)v;
@@ -1849,6 +1921,85 @@ int DLLEXPORT ENsetnodevalue(int index, int code, float v)
} }
break; break;
/*** New parameters added for retrieval begins here ***/ //(2.00.12 - LR)
/*** (Thanks to Nicolas Basile of Ecole Polytechnique ***/
/*** de Montreal for suggesting some of these.) ***/
case EN_TANKDIAM:
if (value <= 0.0) return(202);
j = index - Njuncs;
if (j > 0 && Tank[j].A > 0.0)
{
value /= Ucf[ELEV];
Tank[j].A = PI*SQR(value)/4.0;
Tank[j].Vmin = tankvolume(j, Tank[j].Hmin);
Tank[j].V0 = tankvolume(j, Tank[j].H0);
Tank[j].Vmax = tankvolume(j, Tank[j].Hmax);
}
break;
case EN_MINVOLUME:
if (value < 0.0) return(202);
j = index - Njuncs;
if (j > 0 && Tank[j].A > 0.0)
{
Tank[j].Vmin = value/Ucf[VOLUME];
Tank[j].V0 = tankvolume(j, Tank[j].H0);
Tank[j].Vmax = tankvolume(j, Tank[j].Hmax);
}
break;
case EN_MINLEVEL:
if (value < 0.0) return(202);
j = index - Njuncs;
if (j > 0 && Tank[j].A > 0.0)
{
if (Tank[j].Vcurve > 0) return(202);
Tank[j].Hmin = value/Ucf[ELEV] + Node[index].El;
Tank[j].Vmin = tankvolume(j, Tank[j].Hmin);
}
break;
case EN_MAXLEVEL:
if (value < 0.0) return(202);
j = index - Njuncs;
if (j > 0 && Tank[j].A > 0.0)
{
if (Tank[j].Vcurve > 0) return(202);
Tank[j].Hmax = value/Ucf[ELEV] + Node[index].El;
Tank[j].Vmax = tankvolume(j, Tank[j].Hmax);
}
break;
case EN_MIXMODEL:
j = ROUND(value);
if (j < MIX1 || j > LIFO) return(202);
if (index > Njuncs && Tank[index-Njuncs].A > 0.0)
{
Tank[index-Njuncs].MixModel = (char)j;
}
break;
case EN_MIXFRACTION:
if (value < 0.0 || value > 1.0) return(202);
j = index - Njuncs;
if (j > 0 && Tank[j].A > 0.0)
{
Tank[j].V1max = value*Tank[j].Vmax;
}
break;
case EN_TANK_KBULK:
j = index - Njuncs;
if (j > 0 && Tank[j].A > 0.0)
{
Tank[j].Kb = value/SECperDAY;
Reactflag = 1;
}
break;
/*** New parameter additions ends here. ***/ //(2.00.12 - LR)
default: return(251); default: return(251);
} }
return(0); return(0);
@@ -1953,11 +2104,19 @@ int DLLEXPORT ENsetlinkvalue(int index, int code, float v)
break; break;
case EN_KBULK: case EN_KBULK:
if (Link[index].Type <= PIPE) Link[index].Kb = value/SECperDAY; if (Link[index].Type <= PIPE)
{
Link[index].Kb = value/SECperDAY;
Reactflag = 1; //(2.00.12 - LR)
}
break; break;
case EN_KWALL: case EN_KWALL:
if (Link[index].Type <= PIPE) Link[index].Kw = value/SECperDAY; if (Link[index].Type <= PIPE)
{
Link[index].Kw = value/SECperDAY;
Reactflag = 1; //(2.00.12 - LR)
}
break; break;
default: return(251); default: return(251);
@@ -1965,6 +2124,74 @@ int DLLEXPORT ENsetlinkvalue(int index, int code, float v)
return(0); return(0);
} }
int DLLEXPORT ENaddpattern(char *id)
/*----------------------------------------------------------------
** Input: id = ID name of the new pattern
** Output: none
** Returns: error code
** Purpose: adds a new time pattern appended to the end of the
** existing patterns.
**----------------------------------------------------------------
*/
{
int i, j, n, err = 0;
Spattern *tmpPat;
/* Check if a pattern with same id already exists */
if ( !Openflag ) return(102);
if ( ENgetpatternindex(id, &i) == 0 ) return(215);
/* Check that id name is not too long */
if (strlen(id) > MAXID) return(250);
/* Allocate memory for a new array of patterns */
n = Npats + 1;
tmpPat = (Spattern *) calloc(n+1, sizeof(Spattern));
if ( tmpPat == NULL ) return(101);
/* Copy contents of old pattern array to new one */
for (i=0; i<=Npats; i++)
{
strcpy(tmpPat[i].ID, Pattern[i].ID);
tmpPat[i].Length = Pattern[i].Length;
tmpPat[i].F = (double *) calloc(Pattern[i].Length, sizeof(double));
if (tmpPat[i].F == NULL) err = 1;
else for (j=0; j<Pattern[i].Length; j++)
tmpPat[i].F[j] = Pattern[i].F[j];
}
/* Add the new pattern to the new array of patterns */
strcpy(tmpPat[n].ID, id);
tmpPat[n].Length = 1;
tmpPat[n].F = (double *) calloc(tmpPat[n].Length, sizeof(double));
if (tmpPat[n].F == NULL) err = 1;
else tmpPat[n].F[0] = 1.0;
/* Abort if memory allocation error */
if (err)
{
for (i=0; i<=n; i++) if (tmpPat[i].F) free(tmpPat[i].F);
free(tmpPat);
return(101);
}
// Replace old pattern array with new one
for (i=0; i<=Npats; i++) free(Pattern[i].F);
free(Pattern);
Pattern = tmpPat;
Npats = n;
MaxPats = n;
return 0;
}
int DLLEXPORT ENsetpattern(int index, float *f, int n) int DLLEXPORT ENsetpattern(int index, float *f, int n)
/*---------------------------------------------------------------- /*----------------------------------------------------------------
@@ -2219,6 +2446,8 @@ int openfiles(char *f1, char *f2, char *f3)
strncpy(InpFname,f1,MAXFNAME); strncpy(InpFname,f1,MAXFNAME);
strncpy(Rpt1Fname,f2,MAXFNAME); strncpy(Rpt1Fname,f2,MAXFNAME);
strncpy(OutFname,f3,MAXFNAME); strncpy(OutFname,f3,MAXFNAME);
if (strlen(f3) > 0) Outflag = SAVE; //(2.00.12 - LR)
else Outflag = SCRATCH; //(2.00.12 - LR)
/* Check that file names are not identical */ /* Check that file names are not identical */
if (strcomp(f1,f2) || strcomp(f1,f3) || strcomp(f2,f3)) if (strcomp(f1,f2) || strcomp(f1,f3) || strcomp(f2,f3))
@@ -2271,7 +2500,8 @@ int openhydfile()
HydFile = NULL; HydFile = NULL;
switch(Hydflag) switch(Hydflag)
{ {
case SCRATCH: HydFile = tmpfile(); case SCRATCH: getTmpName(HydFname); //(2.00.12 - LR)
HydFile = fopen(HydFname, "w+b"); //(2.00.12 - LR)
break; break;
case SAVE: HydFile = fopen(HydFname,"w+b"); case SAVE: HydFile = fopen(HydFname,"w+b");
break; break;
@@ -2337,9 +2567,13 @@ int openoutfile()
if (TmpOutFile != NULL) fclose(TmpOutFile); if (TmpOutFile != NULL) fclose(TmpOutFile);
TmpOutFile = NULL; TmpOutFile = NULL;
if (Outflag == SCRATCH) remove(OutFname); //(2.00.12 - LR)
remove(TmpFname); //(2.00.12 - LR)
/* If output file name was supplied, then attempt to */ /* If output file name was supplied, then attempt to */
/* open it. Otherwise open a temporary output file. */ /* open it. Otherwise open a temporary output file. */
if (strlen(OutFname) != 0) //if (strlen(OutFname) != 0) //(2.00.12 - LR)
if (Outflag == SAVE) //(2.00.12 - LR)
{ {
if ( (OutFile = fopen(OutFname,"w+b")) == NULL) if ( (OutFile = fopen(OutFname,"w+b")) == NULL)
{ {
@@ -2347,10 +2581,15 @@ int openoutfile()
errcode = 304; errcode = 304;
} }
} }
else if ( (OutFile = tmpfile()) == NULL) //else if ( (OutFile = tmpfile()) == NULL) //(2.00.12 - LR)
else //(2.00.12 - LR)
{ {
writecon(FMT08); getTmpName(OutFname); //(2.00.12 - LR)
errcode = 304; if ( (OutFile = fopen(OutFname,"w+b")) == NULL) //(2.00.12 - LR)
{
writecon(FMT08);
errcode = 304;
}
} }
/* Save basic network data & energy usage results */ /* Save basic network data & energy usage results */
@@ -2364,7 +2603,10 @@ int openoutfile()
{ {
if (Tstatflag != SERIES) if (Tstatflag != SERIES)
{ {
if ( (TmpOutFile = tmpfile()) == NULL) errcode = 304; //if ( (TmpOutFile = tmpfile()) == NULL) errcode = 304; //(2.00.12 - LR)
getTmpName(TmpFname); //(2.00.12 - LR)
TmpOutFile = fopen(TmpFname, "w+b"); //(2.00.12 - LR)
if (TmpOutFile == NULL) errcode = 304; //(2.00.12 - LR)
} }
else TmpOutFile = OutFile; else TmpOutFile = OutFile;
} }
@@ -2638,6 +2880,50 @@ void freedata()
---------------------------------------------------------------- ----------------------------------------------------------------
*/ */
/*** New function for 2.00.12 ***/ //(2.00.12 - LR)
char* getTmpName(char* fname)
//
// Input: fname = file name string
// Output: returns pointer to file name
// Purpose: creates a temporary file name with path prepended to it.
//
{
char name[MAXFNAME+1];
int n;
// --- for Windows systems:
#ifdef WINDOWS
// --- use system function tmpnam() to create a temporary file name
tmpnam(name);
// --- if user supplied the name of a temporary directory,
// then make it be the prefix of the full file name
n = strlen(TmpDir);
if ( n > 0 )
{
strcpy(fname, TmpDir);
if ( fname[n-1] != '\\' ) strcat(fname, "\\");
}
// --- otherwise, use the relative path notation as the file name
// prefix so that the file will be placed in the current directory
else
{
strcpy(fname, ".\\");
}
// --- now add the prefix to the file name
strcat(fname, name);
// --- for non-Windows systems:
#else
// --- use system function mkstemp() to create a temporary file name
strcpy(fname, "enXXXXXX");
mkstemp(fname);
#endif
return fname;
}
int strcomp(char *s1, char *s2) int strcomp(char *s1, char *s2)
/*--------------------------------------------------------------- /*---------------------------------------------------------------

View File

@@ -1,57 +1,58 @@
LIBRARY EPANET2.DLL LIBRARY EPANET2.DLL
EXPORTS EXPORTS
ENclose @4 ; ENclose ENaddpattern = _ENaddpattern@4
ENcloseH @11 ; ENcloseH ENclose = _ENclose@0
ENcloseQ @20 ; ENcloseQ ENcloseH = _ENcloseH@0
ENepanet @1 ; ENepanet ENcloseQ = _ENcloseQ@0
ENgetcontrol @26 ; ENgetcontrol ENepanet = _ENepanet@16
ENgetcount @27 ; ENgetcount ENgetcontrol = _ENgetcontrol@24
ENgeterror @36 ; ENgeterror ENgetcount = _ENgetcount@8
ENgetflowunits @30 ; ENgetflowunits ENgeterror = _ENgeterror@12
ENgetlinkid @42 ; ENgetlinkid ENgetflowunits = _ENgetflowunits@4
ENgetlinkindex @41 ; ENgetlinkindex ENgetlinkid = _ENgetlinkid@8
ENgetlinknodes @44 ; ENgetlinknodes ENgetlinkindex = _ENgetlinkindex@8
ENgetlinktype @43 ; ENgetlinktype ENgetlinknodes = _ENgetlinknodes@12
ENgetlinkvalue @45 ; ENgetlinkvalue ENgetlinktype = _ENgetlinktype@8
ENgetnodeid @38 ; ENgetnodeid ENgetlinkvalue = _ENgetlinkvalue@12
ENgetnodeindex @37 ; ENgetnodeindex ENgetnodeid = _ENgetnodeid@8
ENgetnodetype @39 ; ENgetnodetype ENgetnodeindex = _ENgetnodeindex@8
ENgetnodevalue @40 ; ENgetnodevalue ENgetnodetype = _ENgetnodetype@8
ENgetoption @28 ; ENgetoption ENgetnodevalue = _ENgetnodevalue@12
ENgetpatternid @32 ; ENgetpatternid ENgetoption = _ENgetoption@8
ENgetpatternindex @31 ; ENgetpatternindex ENgetpatternid = _ENgetpatternid@8
ENgetpatternlen @33 ; ENgetpatternlen ENgetpatternindex = _ENgetpatternindex@8
ENgetpatternvalue @34 ; ENgetpatternvalue ENgetpatternlen = _ENgetpatternlen@8
ENgetqualtype @35 ; ENgetqualtype ENgetpatternvalue = _ENgetpatternvalue@12
ENgettimeparam @29 ; ENgettimeparam ENgetqualtype = _ENgetqualtype@8
ENgetversion @25 ; ENgetversion ENgettimeparam = _ENgettimeparam@8
ENinitH @8 ; ENinitH ENgetversion = _ENgetversion@4
ENinitQ @16 ; ENinitQ ENinitH = _ENinitH@4
ENnextH @10 ; ENnextH ENinitQ = _ENinitQ@4
ENnextQ @18 ; ENnextQ ENnextH = _ENnextH@4
ENopen @2 ; ENopen ENnextQ = _ENnextQ@4
ENopenH @7 ; ENopenH ENopen = _ENopen@12
ENopenQ @15 ; ENopenQ ENopenH = _ENopenH@0
ENreport @22 ; ENreport ENopenQ = _ENopenQ@0
ENresetreport @23 ; ENresetreport ENreport = _ENreport@0
ENrunH @9 ; ENrunH ENresetreport = _ENresetreport@0
ENrunQ @17 ; ENrunQ ENrunH = _ENrunH@4
ENsaveH @6 ; ENsaveH ENrunQ = _ENrunQ@4
ENsavehydfile @12 ; ENsavehydfile ENsaveH = _ENsaveH@0
ENsaveinpfile @3 ; ENsaveinpfile ENsavehydfile = _ENsavehydfile@4
ENsetcontrol @46 ; ENsetcontrol ENsaveinpfile = _ENsaveinpfile@4
ENsetlinkvalue @48 ; ENsetlinkvalue ENsetcontrol = _ENsetcontrol@24
ENsetnodevalue @47 ; ENsetnodevalue ENsetlinkvalue = _ENsetlinkvalue@12
ENsetoption @52 ; ENsetoption ENsetnodevalue = _ENsetnodevalue@12
ENsetpattern @49 ; ENsetpattern ENsetoption = _ENsetoption@8
ENsetpatternvalue @50 ; ENsetpatternvalue ENsetpattern = _ENsetpattern@12
ENsetqualtype @54 ; ENsetqualtype ENsetpatternvalue = _ENsetpatternvalue@12
ENsetreport @24 ; ENsetreport ENsetqualtype = _ENsetqualtype@16
ENsetstatusreport @53 ; ENsetstatusreport ENsetreport = _ENsetreport@4
ENsettimeparam @51 ; ENsettimeparam ENsetstatusreport = _ENsetstatusreport@4
ENsolveH @5 ; ENsolveH ENsettimeparam = _ENsettimeparam@8
ENsolveQ @14 ; ENsolveQ ENsolveH = _ENsolveH@0
ENstepQ @19 ; ENstepQ ENsolveQ = _ENsolveQ@0
ENusehydfile @13 ; ENusehydfile ENstepQ = _ENstepQ@4
ENwriteline @21 ; ENwriteline ENusehydfile = _ENusehydfile@4
ENwriteline = _ENwriteline@4

View File

@@ -3,7 +3,7 @@
** **
** C/C++ header file for EPANET Programmers Toolkit ** C/C++ header file for EPANET Programmers Toolkit
** **
** Last updated on 8/15/07 (2.00.11) ** Last updated on 2/14/08 (2.00.12)
*/ */
#ifndef EPANET2_H #ifndef EPANET2_H
@@ -29,6 +29,14 @@
#define EN_MIXMODEL 15 #define EN_MIXMODEL 15
#define EN_MIXZONEVOL 16 #define EN_MIXZONEVOL 16
#define EN_TANKDIAM 17
#define EN_MINVOLUME 18
#define EN_VOLCURVE 19
#define EN_MINLEVEL 20
#define EN_MAXLEVEL 21
#define EN_MIXFRACTION 22
#define EN_TANK_KBULK 23
#define EN_DIAMETER 0 /* Link parameters */ #define EN_DIAMETER 0 /* Link parameters */
#define EN_LENGTH 1 #define EN_LENGTH 1
#define EN_ROUGHNESS 2 #define EN_ROUGHNESS 2
@@ -113,6 +121,11 @@
#define EN_MAXIMUM 3 #define EN_MAXIMUM 3
#define EN_RANGE 4 #define EN_RANGE 4
#define EN_MIX1 0 /* Tank mixing models */
#define EN_MIX2 1
#define EN_FIFO 2
#define EN_LIFO 3
#define EN_NOSAVE 0 /* Save-results-to-file flag */ #define EN_NOSAVE 0 /* Save-results-to-file flag */
#define EN_SAVE 1 #define EN_SAVE 1
#define EN_INITFLOW 10 /* Re-initialize flow flag */ #define EN_INITFLOW 10 /* Re-initialize flow flag */
@@ -205,6 +218,7 @@
int DLLEXPORT ENsetcontrol(int, int, int, float, int, float); int DLLEXPORT ENsetcontrol(int, int, int, float, int, float);
int DLLEXPORT ENsetnodevalue(int, int, float); int DLLEXPORT ENsetnodevalue(int, int, float);
int DLLEXPORT ENsetlinkvalue(int, int, float); int DLLEXPORT ENsetlinkvalue(int, int, float);
int DLLEXPORT ENaddpattern(char *);
int DLLEXPORT ENsetpattern(int, float *, int); int DLLEXPORT ENsetpattern(int, float *, int);
int DLLEXPORT ENsetpatternvalue(int, int, float); int DLLEXPORT ENsetpatternvalue(int, int, float);
int DLLEXPORT ENsettimeparam(int, long); int DLLEXPORT ENsettimeparam(int, long);

View File

@@ -9,6 +9,7 @@ DATE: 5/8/00
10/25/00 10/25/00
12/29/00 12/29/00
3/1/01 3/1/01
2/14/08 (2.00.12)
AUTHOR: L. Rossman AUTHOR: L. Rossman
US EPA - NRMRL US EPA - NRMRL
@@ -33,7 +34,8 @@ int openfiles(char *,char *,char *); /* Opens input & report files */
int openhydfile(void); /* Opens hydraulics file */ int openhydfile(void); /* Opens hydraulics file */
int openoutfile(void); /* Opens binary output file */ int openoutfile(void); /* Opens binary output file */
int strcomp(char *, char *); /* Compares two strings */ int strcomp(char *, char *); /* Compares two strings */
double interp(int, double *, /* Interpolates a data curve */ char* getTmpName(char* fname); /* Gets temporary file name */ //(2.00.12 - LR)
double interp(int, double *, /* Interpolates a data curve */
double *, double); double *, double);
int findnode(char *); /* Finds node's index from ID */ int findnode(char *); /* Finds node's index from ID */
int findlink(char *); /* Finds link's index from ID */ int findlink(char *); /* Finds link's index from ID */

View File

@@ -12,6 +12,7 @@ DATE: 6/5/00
11/19/01 11/19/01
6/24/02 6/24/02
8/15/07 (2.00.11) 8/15/07 (2.00.11)
2/14/08 (2.00.12)
AUTHOR: L. Rossman AUTHOR: L. Rossman
US EPA - NRMRL US EPA - NRMRL
@@ -1114,12 +1115,14 @@ int netsolve(int *iter, double *relerr)
** using Todini's Gradient algorithm ** using Todini's Gradient algorithm
** **
*** Updated 9/7/00 *** *** Updated 9/7/00 ***
*** Updated 2.00.11 *** *** Updated 2.00.11 ***
*** Updated 2.00.12 ***
** Notes: Status checks on CVs, pumps and pipes to tanks are made ** Notes: Status checks on CVs, pumps and pipes to tanks are made
** every CheckFreq iteration, up until MaxCheck iterations ** every CheckFreq iteration, up until MaxCheck iterations
** are reached. Status checks on control valves are made ** are reached. Status checks on control valves are made
** when within a factor of 10 of convergence. Also at this ** every iteration if DampLimit = 0 or only when the
** point, future computed flow changes are only 60% of ** convergence error is at or below DampLimit. If DampLimit
** is > 0 then future computed flow changes are only 60% of
** their full value. A complete status check on all links ** their full value. A complete status check on all links
** is made when convergence is achieved. If convergence is ** is made when convergence is achieved. If convergence is
** not achieved in MaxIter trials and ExtraIter > 0 then ** not achieved in MaxIter trials and ExtraIter > 0 then
@@ -1135,7 +1138,6 @@ int netsolve(int *iter, double *relerr)
int nextcheck; /* Next status check trial */ int nextcheck; /* Next status check trial */
int maxtrials; /* Max. trials for convergence */ int maxtrials; /* Max. trials for convergence */
double newerr; /* New convergence error */ double newerr; /* New convergence error */
double hacc10 = 10.0*Hacc; /* Relaxed convergence criterion */
int valveChange; /* Valve status change flag */ int valveChange; /* Valve status change flag */
int statChange; int statChange;
@@ -1179,18 +1181,18 @@ int netsolve(int *iter, double *relerr)
/* Write convergence error to status report if called for */ /* Write convergence error to status report if called for */
if (Statflag == FULL) writerelerr(*iter,*relerr); if (Statflag == FULL) writerelerr(*iter,*relerr);
/* Apply relaxation & check valve status if close to convergence */ /* Apply solution damping & check for change in valve status */
RelaxFactor = 1.0;
if ( *relerr <= hacc10) valveChange = FALSE;
if ( DampLimit > 0.0 )
{ {
RelaxFactor = 0.6; if( *relerr <= DampLimit )
valveChange = valvestatus(); {
} RelaxFactor = 0.6;
else valveChange = valvestatus();
{ }
RelaxFactor = 1.0;
valveChange = FALSE;
} }
else valveChange = valvestatus();
/* Check for convergence */ /* Check for convergence */
if (*relerr <= Hacc) if (*relerr <= Hacc)
@@ -1283,7 +1285,7 @@ int valvestatus()
** Input: none ** Input: none
** Output: returns 1 if any pressure or flow control valve //(2.00.11 - LR) ** Output: returns 1 if any pressure or flow control valve //(2.00.11 - LR)
** changes status, 0 otherwise //(2.00.11 - LR) ** changes status, 0 otherwise //(2.00.11 - LR)
** Purpose: updates status for PRVs, PSVs & FCVs whose status //(2.00.11 - LR) ** Purpose: updates status for PRVs & PSVs whose status //(2.00.12 - LR)
** is not fixed to OPEN/CLOSED ** is not fixed to OPEN/CLOSED
**----------------------------------------------------------------- **-----------------------------------------------------------------
*/ */
@@ -1314,8 +1316,9 @@ int valvestatus()
S[k] = psvstatus(k,s,hset,H[n1],H[n2]); S[k] = psvstatus(k,s,hset,H[n1],H[n2]);
break; break;
case FCV: S[k] = fcvstatus(k,s,H[n1],H[n2]); //(2.00.11 - LR) //// FCV status checks moved back into the linkstatus() function //// //(2.00.12 - LR)
break; //(2.00.11 - LR) // case FCV: S[k] = fcvstatus(k,s,H[n1],H[n2]); //(2.00.12 - LR)
// break; //(2.00.12 - LR)
default: continue; default: continue;
} }
@@ -1341,7 +1344,7 @@ int linkstatus()
**-------------------------------------------------------------- **--------------------------------------------------------------
** Input: none ** Input: none
** Output: returns 1 if any link changes status, 0 otherwise ** Output: returns 1 if any link changes status, 0 otherwise
** Purpose: determines new status for pumps, CVs, & pipes //(2.00.11 - LR) ** Purpose: determines new status for pumps, CVs, FCVs & pipes //(2.00.12 - LR)
** to tanks. ** to tanks.
**-------------------------------------------------------------- **--------------------------------------------------------------
*/ */
@@ -1370,8 +1373,8 @@ int linkstatus()
S[k] = pumpstatus(k,-dh); S[k] = pumpstatus(k,-dh);
/* Check for status changes in non-fixed FCVs */ /* Check for status changes in non-fixed FCVs */
//if (Link[k].Type == FCV && K[k] != MISSING) //(2.00.11 - LR) if (Link[k].Type == FCV && K[k] != MISSING) //(2.00.12 - LR)//
// S[k] = fcvstatus(k,status,H[n1],H[n2]); //(2.00.11 - LR) S[k] = fcvstatus(k,status,H[n1],H[n2]); //(2.00.12 - LR)//
/* Check for flow into (out of) full (empty) tanks */ /* Check for flow into (out of) full (empty) tanks */
if (n1 > Njuncs || n2 > Njuncs) tankstatus(k,n1,n2); if (n1 > Njuncs || n2 > Njuncs) tankstatus(k,n1,n2);
@@ -1381,7 +1384,7 @@ int linkstatus()
{ {
change = TRUE; change = TRUE;
if (Statflag == FULL) writestatchange(k,status,S[k]); if (Statflag == FULL) writestatchange(k,status,S[k]);
//if (S[k] <= CLOSED) Q[k] = QZERO; //(2.00.11 - LR) //if (S[k] <= CLOSED) Q[k] = QZERO; //(2.00.11 - LR)
//else setlinkflow(k, dh); //(2.00.11 - LR) //else setlinkflow(k, dh); //(2.00.11 - LR)
} }
@@ -1763,8 +1766,11 @@ double newflows()
dqsum += ABS(dq); dqsum += ABS(dq);
/* Update net flows to tanks */ /* Update net flows to tanks */
if (n1 > Njuncs) D[n1] -= Q[k]; if ( S[k] > CLOSED ) //(2.00.12 - LR)
if (n2 > Njuncs) D[n2] += Q[k]; {
if (n1 > Njuncs) D[n1] -= Q[k];
if (n2 > Njuncs) D[n2] += Q[k];
}
} }

View File

@@ -9,6 +9,7 @@ DATE: 5/8/00
11/19/01 11/19/01
6/24/02 6/24/02
8/15/07 (2.00.11) 8/15/07 (2.00.11)
2/14/08 (2.00.12)
AUTHOR: L. Rossman AUTHOR: L. Rossman
US EPA - NRMRL US EPA - NRMRL
@@ -43,8 +44,12 @@ extern char *RptFlagTxt[];
extern char *SectTxt[]; extern char *SectTxt[];
/*** Updated 6/24/02 ***/ void saveauxdata(FILE *f) //(2.00.12 - LR)
void savemapinfo(FILE *ftmp) /*
------------------------------------------------------------
Writes auxilary data from original input file to new file.
------------------------------------------------------------
*/
{ {
int sect,newsect; int sect,newsect;
char *tok; char *tok;
@@ -55,14 +60,10 @@ void savemapinfo(FILE *ftmp)
rewind(InFile); rewind(InFile);
while (fgets(line,MAXLINE,InFile) != NULL) while (fgets(line,MAXLINE,InFile) != NULL)
{ {
/* Skip blank lines & those beginning with a comment */
strcpy(s,line);
tok = strtok(line,SEPSTR);
if (tok == NULL) continue;
if (*tok == ';') continue;
/* Check if line begins with a new section heading */ /* Check if line begins with a new section heading */
if (*tok == '[') strcpy(s,line);
tok = strtok(s,SEPSTR);
if (tok != NULL && *tok == '[')
{ {
newsect = findmatch(tok,SectTxt); newsect = findmatch(tok,SectTxt);
if (newsect >= 0) if (newsect >= 0)
@@ -76,7 +77,7 @@ void savemapinfo(FILE *ftmp)
case _VERTICES: case _VERTICES:
case _LABELS: case _LABELS:
case _BACKDROP: case _BACKDROP:
case _TAGS: fwrite(s, sizeof(char), strlen(s), ftmp); case _TAGS: fprintf(f, "%s", line); //(2.00.12 - LR)
} }
continue; continue;
} }
@@ -91,13 +92,14 @@ void savemapinfo(FILE *ftmp)
case _VERTICES: case _VERTICES:
case _LABELS: case _LABELS:
case _BACKDROP: case _BACKDROP:
case _TAGS: fwrite(s, sizeof(char), strlen(s), ftmp); case _TAGS: fprintf(f, "%s", line); //(2.00.12 - LR)
} }
} }
} }
/*** End of update ***/
//// This function was heavily modified. //// //(2.00.12 - LR)
int saveinpfile(char *fname) int saveinpfile(char *fname)
/* /*
------------------------------------------------- -------------------------------------------------
@@ -105,38 +107,16 @@ int saveinpfile(char *fname)
------------------------------------------------- -------------------------------------------------
*/ */
{ {
int i,j,n; int i,j,n;
double d,kc,ke,km,ucf; double d,kc,ke,km,ucf;
char s[MAXLINE+1], s1[MAXLINE+1], s2[MAXLINE+1];
/*** Updated 6/24/02 ***/
char s[MAXLINE+1], s1[MAXLINE+1], s2[MAXLINE+1];
Pdemand demand; Pdemand demand;
Psource source; Psource source;
FILE *f; FILE *f;
/*** Updated 6/24/02 ***/ /* Open the new text file */
FILE *ftmp;
/* Copy [RULES], [COORDS], [VERTICES], [LABELS], [BACKDROP] & [TAGS] */ if ((f = fopen(fname,"wt")) == NULL) return(308);
/* sections from original input file to new input file */
ftmp = NULL;
if (InFile)
{
ftmp = tmpfile();
if (ftmp) savemapinfo(ftmp);
}
/* Open text file */
if ((f = fopen(fname,"wt")) == NULL)
{
if (ftmp) fclose(ftmp);
return(102);
}
/*** End of update ***/
/* Write [TITLE] section */ /* Write [TITLE] section */
@@ -151,7 +131,7 @@ int saveinpfile(char *fname)
fprintf(f,"\n\n[JUNCTIONS]"); fprintf(f,"\n\n[JUNCTIONS]");
for (i=1; i<=Njuncs; i++) for (i=1; i<=Njuncs; i++)
fprintf(f,"\n %-15s %12.2f", Node[i].ID, Node[i].El*Ucf[ELEV]); fprintf(f,"\n %-31s %12.4f", Node[i].ID, Node[i].El*Ucf[ELEV]);
/* Write [RESERVOIRS] section */ /* Write [RESERVOIRS] section */
@@ -161,9 +141,9 @@ int saveinpfile(char *fname)
if (Tank[i].A == 0.0) if (Tank[i].A == 0.0)
{ {
n = Tank[i].Node; n = Tank[i].Node;
sprintf(s," %-15s %12.2f",Node[n].ID, Node[n].El*Ucf[ELEV]); sprintf(s," %-31s %12.4f",Node[n].ID, Node[n].El*Ucf[ELEV]);
if ((j = Tank[i].Pat) > 0) if ((j = Tank[i].Pat) > 0)
sprintf(s1," %-15s",Pattern[j].ID); sprintf(s1," %-31s",Pattern[j].ID);
else else
strcpy(s1,""); strcpy(s1,"");
fprintf(f, "\n%s %s", s,s1); fprintf(f, "\n%s %s", s,s1);
@@ -178,7 +158,7 @@ int saveinpfile(char *fname)
if (Tank[i].A > 0.0) if (Tank[i].A > 0.0)
{ {
n = Tank[i].Node; n = Tank[i].Node;
sprintf(s," %-15s %12.2f %12.2f %12.2f %12.2f %12.2f %12.2f", sprintf(s," %-31s %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f",
Node[n].ID, Node[n].ID,
Node[n].El*Ucf[ELEV], Node[n].El*Ucf[ELEV],
(Tank[i].H0 - Node[n].El)*Ucf[ELEV], (Tank[i].H0 - Node[n].El)*Ucf[ELEV],
@@ -187,7 +167,7 @@ int saveinpfile(char *fname)
sqrt(4.0*Tank[i].A/PI)*Ucf[ELEV], sqrt(4.0*Tank[i].A/PI)*Ucf[ELEV],
Tank[i].Vmin*SQR(Ucf[ELEV])*Ucf[ELEV]); Tank[i].Vmin*SQR(Ucf[ELEV])*Ucf[ELEV]);
if ((j = Tank[i].Vcurve) > 0) if ((j = Tank[i].Vcurve) > 0)
sprintf(s1,"%-15s",Curve[j].ID); sprintf(s1,"%-31s",Curve[j].ID);
else else
strcpy(s1,""); strcpy(s1,"");
fprintf(f, "\n%s %s", s,s1); fprintf(f, "\n%s %s", s,s1);
@@ -205,21 +185,18 @@ int saveinpfile(char *fname)
kc = Link[i].Kc; kc = Link[i].Kc;
if (Formflag == DW) kc = kc*Ucf[ELEV]*1000.0; if (Formflag == DW) kc = kc*Ucf[ELEV]*1000.0;
km = Link[i].Km*SQR(d)*SQR(d)/0.02517; km = Link[i].Km*SQR(d)*SQR(d)/0.02517;
sprintf(s," %-31s %-31s %-31s %12.4f %12.4f",
/*** Updated 6/24/02 ***/
sprintf(s," %-15s %-15s %-15s %12.2f %12.2f",
Link[i].ID, Link[i].ID,
Node[Link[i].N1].ID, Node[Link[i].N1].ID,
Node[Link[i].N2].ID, Node[Link[i].N2].ID,
Link[i].Len*Ucf[LENGTH], Link[i].Len*Ucf[LENGTH],
d*Ucf[DIAM]); d*Ucf[DIAM]);
if (Formflag == DW) sprintf(s1, "%12.4f %12.4f", kc, km); if (Formflag == DW) sprintf(s1, "%12.4f %12.4f", kc, km);
else sprintf(s1, "%12.2f %12.4f", kc, km); else sprintf(s1, "%12.4f %12.4f", kc, km);
if (Link[i].Type == CV) sprintf(s2,"CV"); if (Link[i].Type == CV) sprintf(s2,"CV");
else if (Link[i].Stat == CLOSED) sprintf(s2,"CLOSED"); else if (Link[i].Stat == CLOSED) sprintf(s2,"CLOSED");
else strcpy(s2,""); else strcpy(s2,"");
fprintf(f,"\n%s %s %s",s,s1,s2); fprintf(f,"\n%s %s %s",s,s1,s2);
/*** End of update ***/
} }
} }
@@ -229,14 +206,14 @@ int saveinpfile(char *fname)
for (i=1; i<=Npumps; i++) for (i=1; i<=Npumps; i++)
{ {
n = Pump[i].Link; n = Pump[i].Link;
sprintf(s," %-15s %-15s %-15s", sprintf(s," %-31s %-31s %-31s",
Link[n].ID, Link[n].ID,
Node[Link[n].N1].ID, Node[Link[n].N1].ID,
Node[Link[n].N2].ID); Node[Link[n].N2].ID);
/* Pump has constant power */ /* Pump has constant power */
if (Pump[i].Ptype == CONST_HP) if (Pump[i].Ptype == CONST_HP)
sprintf(s1, " POWER %.2f", Link[n].Km); sprintf(s1, " POWER %.4f", Link[n].Km);
/* Pump has a head curve */ /* Pump has a head curve */
else if ((j = Pump[i].Hcurve) > 0) else if ((j = Pump[i].Hcurve) > 0)
@@ -245,7 +222,7 @@ int saveinpfile(char *fname)
/* Old format used for pump curve */ /* Old format used for pump curve */
else else
{ {
fprintf(f, "\n%s %12.2f %12.2f %12.2f 0.0 %12.2f",s, fprintf(f, "\n%s %12.4f %12.4f %12.4f 0.0 %12.4f",s,
-Pump[i].H0*Ucf[HEAD], -Pump[i].H0*Ucf[HEAD],
(-Pump[i].H0 - Pump[i].R*pow(Pump[i].Q0,Pump[i].N))*Ucf[HEAD], (-Pump[i].H0 - Pump[i].R*pow(Pump[i].Q0,Pump[i].N))*Ucf[HEAD],
Pump[i].Q0*Ucf[FLOW], Pump[i].Q0*Ucf[FLOW],
@@ -260,7 +237,7 @@ int saveinpfile(char *fname)
strcat(s,s1); strcat(s,s1);
if (Link[n].Kc != 1.0) if (Link[n].Kc != 1.0)
sprintf(s1, " SPEED %.2f", Link[n].Kc); sprintf(s1, " SPEED %.4f", Link[n].Kc);
else strcpy(s1,""); else strcpy(s1,"");
strcat(s,s1); strcat(s,s1);
@@ -285,7 +262,7 @@ int saveinpfile(char *fname)
} }
km = Link[n].Km*SQR(d)*SQR(d)/0.02517; km = Link[n].Km*SQR(d)*SQR(d)/0.02517;
sprintf(s," %-15s %-15s %-15s %12.2f %5s", sprintf(s," %-31s %-31s %-31s %12.4f %5s",
Link[n].ID, Link[n].ID,
Node[Link[n].N1].ID, Node[Link[n].N1].ID,
Node[Link[n].N2].ID, Node[Link[n].N2].ID,
@@ -293,8 +270,8 @@ int saveinpfile(char *fname)
LinkTxt[Link[n].Type]); LinkTxt[Link[n].Type]);
if (Link[n].Type == GPV && (j = ROUND(Link[n].Kc)) > 0) if (Link[n].Type == GPV && (j = ROUND(Link[n].Kc)) > 0)
sprintf(s1,"%-15s %12.2f", Curve[j].ID, km); sprintf(s1,"%-31s %12.4f", Curve[j].ID, km);
else sprintf(s1,"%12.2f %12.2f",kc,km); else sprintf(s1,"%12.4f %12.4f",kc,km);
fprintf(f, "\n%s %s", s,s1); fprintf(f, "\n%s %s", s,s1);
} }
@@ -302,15 +279,12 @@ int saveinpfile(char *fname)
/* Write [DEMANDS] section */ /* Write [DEMANDS] section */
fprintf(f, "\n\n[DEMANDS]"); fprintf(f, "\n\n[DEMANDS]");
/*** Updated 11/19/01 ***/
ucf = Ucf[DEMAND]; ucf = Ucf[DEMAND];
for (i=1; i<=Njuncs; i++) for (i=1; i<=Njuncs; i++)
{ {
for (demand = Node[i].D; demand != NULL; demand = demand->next) for (demand = Node[i].D; demand != NULL; demand = demand->next)
{ {
sprintf(s," %-15s %12.2f",Node[i].ID,ucf*demand->Base); sprintf(s," %-31s %14.6f",Node[i].ID,ucf*demand->Base);
if ((j = demand->Pat) > 0) sprintf(s1," %s",Pattern[j].ID); if ((j = demand->Pat) > 0) sprintf(s1," %s",Pattern[j].ID);
else strcpy(s1,""); else strcpy(s1,"");
fprintf(f,"\n%s %s",s,s1); fprintf(f,"\n%s %s",s,s1);
@@ -324,7 +298,7 @@ int saveinpfile(char *fname)
{ {
if (Node[i].Ke == 0.0) continue; if (Node[i].Ke == 0.0) continue;
ke = Ucf[FLOW]/pow(Ucf[PRESSURE]*Node[i].Ke,(1.0/Qexp)); ke = Ucf[FLOW]/pow(Ucf[PRESSURE]*Node[i].Ke,(1.0/Qexp));
fprintf(f,"\n %-15s %12.2f",Node[i].ID,ke); fprintf(f,"\n %-31s %14.6f",Node[i].ID,ke);
} }
/* Write [STATUS] section */ /* Write [STATUS] section */
@@ -335,7 +309,7 @@ int saveinpfile(char *fname)
if (Link[i].Type <= PUMP) if (Link[i].Type <= PUMP)
{ {
if (Link[i].Stat == CLOSED) if (Link[i].Stat == CLOSED)
fprintf(f, "\n %-15s %s",Link[i].ID,StatTxt[CLOSED]); fprintf(f, "\n %-31s %s",Link[i].ID,StatTxt[CLOSED]);
/* Write pump speed here for pumps with old-style pump curve input */ /* Write pump speed here for pumps with old-style pump curve input */
else if (Link[i].Type == PUMP) else if (Link[i].Type == PUMP)
@@ -346,7 +320,7 @@ int saveinpfile(char *fname)
Pump[n].Ptype != CONST_HP && Pump[n].Ptype != CONST_HP &&
Link[i].Kc != 1.0 Link[i].Kc != 1.0
) )
fprintf(f, "\n %-15s %-.2f",Link[i].ID, Link[i].Kc); fprintf(f, "\n %-31s %-.4f",Link[i].ID, Link[i].Kc);
} }
} }
@@ -354,9 +328,9 @@ int saveinpfile(char *fname)
else if (Link[i].Kc == MISSING) else if (Link[i].Kc == MISSING)
{ {
if (Link[i].Stat == OPEN) if (Link[i].Stat == OPEN)
fprintf(f, "\n %-15s %s",Link[i].ID,StatTxt[OPEN]); fprintf(f, "\n %-31s %s",Link[i].ID,StatTxt[OPEN]);
if (Link[i].Stat == CLOSED) if (Link[i].Stat == CLOSED)
fprintf(f, "\n%-15s %s",Link[i].ID,StatTxt[CLOSED]); fprintf(f, "\n%-31s %s",Link[i].ID,StatTxt[CLOSED]);
} }
} }
@@ -368,7 +342,7 @@ int saveinpfile(char *fname)
{ {
for (j=0; j<Pattern[i].Length; j++) for (j=0; j<Pattern[i].Length; j++)
{ {
if (j % 6 == 0) fprintf(f,"\n %-15s",Pattern[i].ID); if (j % 6 == 0) fprintf(f,"\n %-31s",Pattern[i].ID);
fprintf(f," %12.4f",Pattern[i].F[j]); fprintf(f," %12.4f",Pattern[i].F[j]);
} }
} }
@@ -379,7 +353,7 @@ int saveinpfile(char *fname)
for (i=1; i<=Ncurves; i++) for (i=1; i<=Ncurves; i++)
{ {
for (j=0; j<Curve[i].Npts; j++) for (j=0; j<Curve[i].Npts; j++)
fprintf(f,"\n %-15s %12.4f %12.4f", fprintf(f,"\n %-31s %12.4f %12.4f",
Curve[i].ID,Curve[i].X[j],Curve[i].Y[j]); Curve[i].ID,Curve[i].X[j],Curve[i].Y[j]);
} }
@@ -422,7 +396,7 @@ int saveinpfile(char *fname)
/* Print timer control */ /* Print timer control */
case TIMER: case TIMER:
fprintf(f, "\n%s AT %s %.2f HOURS", fprintf(f, "\n%s AT %s %.4f HOURS",
s, ControlTxt[TIMER], Control[i].Time/3600.); s, ControlTxt[TIMER], Control[i].Time/3600.);
break; break;
@@ -441,7 +415,7 @@ int saveinpfile(char *fname)
for (i=1; i<=Nnodes; i++) for (i=1; i<=Nnodes; i++)
{ {
if (Node[i].C0 == 0.0) continue; if (Node[i].C0 == 0.0) continue;
fprintf(f, "\n %-15s %12.3f",Node[i].ID,Node[i].C0*Ucf[QUALITY]); fprintf(f, "\n %-31s %14.6f",Node[i].ID,Node[i].C0*Ucf[QUALITY]);
} }
/* Write [SOURCES] section */ /* Write [SOURCES] section */
@@ -451,7 +425,7 @@ int saveinpfile(char *fname)
{ {
source = Node[i].S; source = Node[i].S;
if (source == NULL) continue; if (source == NULL) continue;
sprintf(s," %-15s %-8s %12.2f", sprintf(s," %-31s %-8s %14.6f",
Node[i].ID, Node[i].ID,
SourceTxt[source->Type], SourceTxt[source->Type],
source->C0); source->C0);
@@ -467,7 +441,7 @@ int saveinpfile(char *fname)
for (i=1; i<=Ntanks; i++) for (i=1; i<=Ntanks; i++)
{ {
if (Tank[i].A == 0.0) continue; if (Tank[i].A == 0.0) continue;
fprintf(f, "\n %-15s %-8s %12.4f", fprintf(f, "\n %-31s %-8s %12.4f",
Node[Tank[i].Node].ID, Node[Tank[i].Node].ID,
MixTxt[Tank[i].MixModel], MixTxt[Tank[i].MixModel],
(Tank[i].V1max/Tank[i].Vmax)); (Tank[i].V1max/Tank[i].Vmax));
@@ -479,25 +453,25 @@ int saveinpfile(char *fname)
fprintf(f, "\n ORDER BULK %-.2f", BulkOrder); fprintf(f, "\n ORDER BULK %-.2f", BulkOrder);
fprintf(f, "\n ORDER WALL %-.0f", WallOrder); fprintf(f, "\n ORDER WALL %-.0f", WallOrder);
fprintf(f, "\n ORDER TANK %-.2f", TankOrder); fprintf(f, "\n ORDER TANK %-.2f", TankOrder);
fprintf(f, "\n GLOBAL BULK %-.4f", Kbulk*SECperDAY); fprintf(f, "\n GLOBAL BULK %-.6f", Kbulk*SECperDAY);
fprintf(f, "\n GLOBAL WALL %-.4f", Kwall*SECperDAY); fprintf(f, "\n GLOBAL WALL %-.6f", Kwall*SECperDAY);
if (Climit > 0.0) if (Climit > 0.0)
fprintf(f, "\n LIMITING POTENTIAL %-.4f", Climit); fprintf(f, "\n LIMITING POTENTIAL %-.6f", Climit);
if (Rfactor != MISSING && Rfactor != 0.0) if (Rfactor != MISSING && Rfactor != 0.0)
fprintf(f, "\n ROUGHNESS CORRELATION %-.4f",Rfactor); fprintf(f, "\n ROUGHNESS CORRELATION %-.6f",Rfactor);
for (i=1; i<=Nlinks; i++) for (i=1; i<=Nlinks; i++)
{ {
if (Link[i].Type > PIPE) continue; if (Link[i].Type > PIPE) continue;
if (Link[i].Kb != Kbulk) if (Link[i].Kb != Kbulk)
fprintf(f, "\n BULK %-15s %-.4f",Link[i].ID,Link[i].Kb*SECperDAY); fprintf(f, "\n BULK %-31s %-.6f",Link[i].ID,Link[i].Kb*SECperDAY);
if (Link[i].Kw != Kwall) if (Link[i].Kw != Kwall)
fprintf(f, "\n WALL %-15s %-.4f",Link[i].ID,Link[i].Kw*SECperDAY); fprintf(f, "\n WALL %-31s %-.6f",Link[i].ID,Link[i].Kw*SECperDAY);
} }
for (i=1; i<=Ntanks; i++) for (i=1; i<=Ntanks; i++)
{ {
if (Tank[i].A == 0.0) continue; if (Tank[i].A == 0.0) continue;
if (Tank[i].Kb != Kbulk) if (Tank[i].Kb != Kbulk)
fprintf(f, "\n TANK %-15s %-.4f",Node[Tank[i].Node].ID, fprintf(f, "\n TANK %-31s %-.6f",Node[Tank[i].Node].ID,
Tank[i].Kb*SECperDAY); Tank[i].Kb*SECperDAY);
} }
@@ -508,20 +482,18 @@ int saveinpfile(char *fname)
fprintf(f, "\n GLOBAL PRICE %-.4f", Ecost); fprintf(f, "\n GLOBAL PRICE %-.4f", Ecost);
if (Epat != 0) if (Epat != 0)
fprintf(f, "\n GLOBAL PATTERN %s", Pattern[Epat].ID); fprintf(f, "\n GLOBAL PATTERN %s", Pattern[Epat].ID);
fprintf(f, "\n GLOBAL EFFIC %-.2f", Epump); fprintf(f, "\n GLOBAL EFFIC %-.4f", Epump);
fprintf(f, "\n DEMAND CHARGE %-.4f", Dcost); fprintf(f, "\n DEMAND CHARGE %-.4f", Dcost);
for (i=1; i<=Npumps; i++) for (i=1; i<=Npumps; i++)
{ {
if (Pump[i].Ecost > 0.0) if (Pump[i].Ecost > 0.0)
fprintf(f, "\n PUMP %-15s PRICE %-.4f", fprintf(f, "\n PUMP %-31s PRICE %-.4f",
Link[Pump[i].Link].ID,Pump[i].Ecost); Link[Pump[i].Link].ID,Pump[i].Ecost);
if (Pump[i].Epat > 0.0) if (Pump[i].Epat > 0.0)
fprintf(f, "\n PUMP %-15s PATTERN %s", fprintf(f, "\n PUMP %-31s PATTERN %s",
Link[Pump[i].Link].ID,Pattern[Pump[i].Epat].ID); Link[Pump[i].Link].ID,Pattern[Pump[i].Epat].ID);
/*** Updated 3/1/01 ***/
if (Pump[i].Ecurve > 0.0) if (Pump[i].Ecurve > 0.0)
fprintf(f, "\n PUMP %-15s EFFIC %s", fprintf(f, "\n PUMP %-31s EFFIC %s",
Link[Pump[i].Link].ID,Curve[Pump[i].Ecurve].ID); Link[Pump[i].Link].ID,Curve[Pump[i].Ecurve].ID);
} }
@@ -558,22 +530,22 @@ int saveinpfile(char *fname)
if (Qualflag == CHEM) if (Qualflag == CHEM)
fprintf(f, "\n QUALITY %s %s", ChemName, ChemUnits); fprintf(f, "\n QUALITY %s %s", ChemName, ChemUnits);
if (Qualflag == TRACE) if (Qualflag == TRACE)
fprintf(f, "\n QUALITY TRACE %-15s", Node[TraceNode].ID); fprintf(f, "\n QUALITY TRACE %-31s", Node[TraceNode].ID);
if (Qualflag == AGE) if (Qualflag == AGE)
fprintf(f, "\n QUALITY AGE"); fprintf(f, "\n QUALITY AGE");
if (Qualflag == NONE) if (Qualflag == NONE)
fprintf(f, "\n QUALITY NONE"); fprintf(f, "\n QUALITY NONE");
fprintf(f, "\n DEMAND MULTIPLIER %-.2f", Dmult); fprintf(f, "\n DEMAND MULTIPLIER %-.4f", Dmult);
fprintf(f, "\n EMITTER EXPONENT %-.4f", 1.0/Qexp);
/*** Updated 11/19/01 ***/ fprintf(f, "\n VISCOSITY %-.6f", Viscos/VISCOS);
fprintf(f, "\n EMITTER EXPONENT %-.2f", 1.0/Qexp); fprintf(f, "\n DIFFUSIVITY %-.6f", Diffus/DIFFUS);
fprintf(f, "\n SPECIFIC GRAVITY %-.6f", SpGrav);
fprintf(f, "\n VISCOSITY %-.4f", Viscos/VISCOS);
fprintf(f, "\n DIFFUSIVITY %-.4f", Diffus/DIFFUS);
fprintf(f, "\n SPECIFIC GRAVITY %-.4f", SpGrav);
fprintf(f, "\n TRIALS %-d", MaxIter); fprintf(f, "\n TRIALS %-d", MaxIter);
fprintf(f, "\n ACCURACY %-.8f", Hacc); fprintf(f, "\n ACCURACY %-.8f", Hacc);
fprintf(f, "\n TOLERANCE %-.8f", Ctol*Ucf[QUALITY]); fprintf(f, "\n TOLERANCE %-.8f", Ctol*Ucf[QUALITY]);
fprintf(f, "\n CHECKFREQ %-d", CheckFreq);
fprintf(f, "\n MAXCHECK %-d", MaxCheck);
fprintf(f, "\n DAMPLIMIT %-.8f", DampLimit);
/* Write [REPORT] section */ /* Write [REPORT] section */
@@ -622,33 +594,27 @@ int saveinpfile(char *fname)
} }
} }
} }
for (i=0; i<MAXVAR; i++) for (i=0; i<FRICTION; i++)
{ {
/*** Updated ********************************************************/ //(2.00.11 - LR)
if (Field[i].Enabled == TRUE) if (Field[i].Enabled == TRUE)
{ {
fprintf(f, "\n %-20sPRECISION %d", Field[i].Name, Field[i].Precision); fprintf(f, "\n %-20sPRECISION %d", Field[i].Name, Field[i].Precision);
if (Field[i].RptLim[LOW] < BIG) if (Field[i].RptLim[LOW] < BIG)
fprintf(f, "\n %-20sBELOW %.4f", Field[i].Name, Field[i].RptLim[LOW]); fprintf(f, "\n %-20sBELOW %.6f", Field[i].Name, Field[i].RptLim[LOW]);
if (Field[i].RptLim[HI] > -BIG) if (Field[i].RptLim[HI] > -BIG)
fprintf(f, "\n %-20sABOVE %.4f", Field[i].Name, Field[i].RptLim[HI]); fprintf(f, "\n %-20sABOVE %.6f", Field[i].Name, Field[i].RptLim[HI]);
} }
else fprintf(f, "\n %-20sNO", Field[i].Name); else fprintf(f, "\n %-20sNO", Field[i].Name);
/********************************************************************/
} }
fprintf(f, "\n"); fprintf(f, "\n");
/*** Updated *****************************************/ //(2.00.11 - LR) /* Save auxilary data to new input file */
/* Copy data from scratch file to new input file */
if (ftmp != NULL) saveauxdata(f);
{
fseek(ftmp, 0, SEEK_SET);
while ( (j = fgetc(ftmp)) != EOF ) fputc(j, f);
fclose(ftmp);
}
/*****************************************************/
fprintf(f, "\n\n[END]"); /* Close the new input file */
fprintf(f, "\n[END]");
fclose(f); fclose(f);
return(0); return(0);
} }

View File

@@ -8,6 +8,7 @@ DATE: 5/30/00
9/7/00 9/7/00
11/19/01 11/19/01
6/24/02 6/24/02
2/14/08 (2.00.12)
AUTHOR: L. Rossman AUTHOR: L. Rossman
US EPA - NRMRL US EPA - NRMRL
@@ -36,7 +37,7 @@ AUTHOR: L. Rossman
--------------------- Module Global Variables ---------------------- --------------------- Module Global Variables ----------------------
*/ */
#define MAXITER 40 /* Default max. # hydraulic iterations */ #define MAXITER 200 /* Default max. # hydraulic iterations */ //(2.00.12 - LR)
#define HACC 0.001 /* Default hydraulics convergence ratio */ #define HACC 0.001 /* Default hydraulics convergence ratio */
#define HTOL 0.0005 /* Default hydraulic head tolerance (ft) */ #define HTOL 0.0005 /* Default hydraulic head tolerance (ft) */
@@ -57,6 +58,7 @@ AUTHOR: L. Rossman
#define RQTOL 1E-7 /* Default low flow resistance tolerance */ #define RQTOL 1E-7 /* Default low flow resistance tolerance */
#define CHECKFREQ 2 /* Default status check frequency */ #define CHECKFREQ 2 /* Default status check frequency */
#define MAXCHECK 10 /* Default # iterations for status checks */ #define MAXCHECK 10 /* Default # iterations for status checks */
#define DAMPLIMIT 0 /* Default damping threshold */ //(2.00.12 - LR)
extern char *Fldname[]; /* Defined in enumstxt.h in EPANET.C */ extern char *Fldname[]; /* Defined in enumstxt.h in EPANET.C */
extern char *RptFlowUnitsTxt[]; extern char *RptFlowUnitsTxt[];
@@ -96,6 +98,8 @@ void setdefaults()
strncpy(Title[0],"",MAXMSG); strncpy(Title[0],"",MAXMSG);
strncpy(Title[1],"",MAXMSG); strncpy(Title[1],"",MAXMSG);
strncpy(Title[2],"",MAXMSG); strncpy(Title[2],"",MAXMSG);
strncpy(TmpDir,"",MAXFNAME); //(2.00.12 - LR)
strncpy(TmpFname,"",MAXFNAME); //(2.00.12 - LR)
strncpy(HydFname,"",MAXFNAME); strncpy(HydFname,"",MAXFNAME);
strncpy(MapFname,"",MAXFNAME); strncpy(MapFname,"",MAXFNAME);
strncpy(ChemName,t_CHEMICAL,MAXID); strncpy(ChemName,t_CHEMICAL,MAXID);
@@ -146,6 +150,7 @@ void setdefaults()
RQtol = RQTOL; /* Default hydraulics parameters */ RQtol = RQTOL; /* Default hydraulics parameters */
CheckFreq = CHECKFREQ; CheckFreq = CHECKFREQ;
MaxCheck = MAXCHECK; MaxCheck = MAXCHECK;
DampLimit = DAMPLIMIT; //(2.00.12 - LR)
} /* End of setdefaults */ } /* End of setdefaults */

View File

@@ -10,6 +10,7 @@ DATE: 5/30/00
3/1/01 3/1/01
6/24/02 6/24/02
8/15/07 (2.00.11) 8/15/07 (2.00.11)
2/14/08 (2.00.12)
AUTHOR: L. Rossman AUTHOR: L. Rossman
US EPA - NRMRL US EPA - NRMRL
@@ -1599,7 +1600,8 @@ int optionvalue(int n)
** QTOL value ** QTOL value
** RQTOL value ** RQTOL value
** CHECKFREQ value ** CHECKFREQ value
** MAXCHECK value ** MAXCHECK value
** DAMPLIMIT value //(2.00.12 - LR)
**-------------------------------------------------------------- **--------------------------------------------------------------
*/ */
{ {
@@ -1633,6 +1635,13 @@ int optionvalue(int n)
return(0); return(0);
} }
/* Check for Damping Limit option */ //(2.00.12 - LR)
if (match(Tok[0],w_DAMPLIMIT))
{
DampLimit = y;
return(0);
}
/* All other options must be > 0 */ /* All other options must be > 0 */
if (y <= 0.0) return(213); if (y <= 0.0) return(213);

View File

@@ -8,6 +8,7 @@ DATE: 5/29/00
9/7/00 9/7/00
10/25/00 10/25/00
8/15/07 (2.00.11) 8/15/07 (2.00.11)
2/14/08 (2.00.12)
AUTHOR: L. Rossman AUTHOR: L. Rossman
US EPA - NRMRL US EPA - NRMRL
@@ -75,7 +76,10 @@ double *MassIn; /* Total mass inflow to node */
double Sc; /* Schmidt Number */ double Sc; /* Schmidt Number */
double Bucf; /* Bulk reaction units conversion factor */ double Bucf; /* Bulk reaction units conversion factor */
double Tucf; /* Tank reaction units conversion factor */ double Tucf; /* Tank reaction units conversion factor */
char Reactflag; /* Reaction indicator */
/*** Moved to vars.h ***/ //(2.00.12 - LR)
//char Reactflag; /* Reaction indicator */
char OutOfMemory; /* Out of memory indicator */ char OutOfMemory; /* Out of memory indicator */
static alloc_handle_t *SegPool; // Memory pool for water quality segments //(2.00.11 - LR) static alloc_handle_t *SegPool; // Memory pool for water quality segments //(2.00.11 - LR)
@@ -688,10 +692,12 @@ void accumulate(long dt)
i = UP_NODE(k); /* Upstream node */ i = UP_NODE(k); /* Upstream node */
j = DOWN_NODE(k); /* Downstream node */ j = DOWN_NODE(k); /* Downstream node */
v = ABS(Q[k])*dt; /* Flow volume */ v = ABS(Q[k])*dt; /* Flow volume */
//// Start of deprecated code segment //// //(2.00.12 - LR)
/* If link volume < flow volume, then transport upstream */ /* If link volume < flow volume, then transport upstream */
/* quality to downstream node and remove all link segments. */ /* quality to downstream node and remove all link segments. */
if (LINKVOL(k) < v) /* if (LINKVOL(k) < v)
{ {
VolIn[j] += v; VolIn[j] += v;
seg = FirstSeg[k]; seg = FirstSeg[k];
@@ -700,10 +706,14 @@ void accumulate(long dt)
MassIn[j] += v*cseg; MassIn[j] += v*cseg;
removesegs(k); removesegs(k);
} }
*/
/* Otherwise remove flow volume from leading segments */ /* Otherwise remove flow volume from leading segments */
/* and accumulate flow mass at downstream node */ /* and accumulate flow mass at downstream node */
else while (v > 0.0) //else
//// End of deprecated code segment. //// //(2.00.12 - LR)
while (v > 0.0) //(2.00.12 - LR)
{ {
/* Identify leading segment in pipe */ /* Identify leading segment in pipe */
seg = FirstSeg[k]; seg = FirstSeg[k];
@@ -1003,6 +1013,37 @@ void updatetanks(long dt)
} }
//// Deprecated version of tankmix1 //// //(2.00.12 - LR)
//void tankmix1(int i, long dt)
/*
**---------------------------------------------
** Input: i = tank index
** dt = current WQ time step
** Output: none
** Purpose: complete mix tank model
**---------------------------------------------
*/
//{
// int n;
// double cin;
// /* Blend inflow with contents */
// n = Tank[i].Node;
// if (VolIn[n] > 0.0) cin = MassIn[n]/VolIn[n];
// else cin = 0.0;
// if (Tank[i].V > 0.0)
// Tank[i].C = tankreact(Tank[i].C,Tank[i].V,Tank[i].Kb,dt) +
// (cin - Tank[i].C)*VolIn[n]/Tank[i].V;
// else Tank[i].C = cin;
// Tank[i].C = MAX(0.0, Tank[i].C);
// /* Update tank volume & nodal quality */
// Tank[i].V += D[n]*dt;
// C[n] = Tank[i].C;
//}
//// New version of tankmix1 //// //(2.00.12 - LR)
void tankmix1(int i, long dt) void tankmix1(int i, long dt)
/* /*
**--------------------------------------------- **---------------------------------------------
@@ -1015,23 +1056,32 @@ void tankmix1(int i, long dt)
{ {
int n; int n;
double cin; double cin;
double c, cmax, vold, vin;
/* Blend inflow with contents */ /* React contents of tank */
c = tankreact(Tank[i].C,Tank[i].V,Tank[i].Kb,dt);
/* Determine tank & volumes */
vold = Tank[i].V;
n = Tank[i].Node; n = Tank[i].Node;
if (VolIn[n] > 0.0) cin = MassIn[n]/VolIn[n];
else cin = 0.0;
if (Tank[i].V > 0.0)
Tank[i].C = tankreact(Tank[i].C,Tank[i].V,Tank[i].Kb,dt) +
(cin - Tank[i].C)*VolIn[n]/Tank[i].V;
else Tank[i].C = cin;
Tank[i].C = MAX(0.0, Tank[i].C);
/* Update tank volume & nodal quality */
Tank[i].V += D[n]*dt; Tank[i].V += D[n]*dt;
vin = VolIn[n];
/* Compute inflow concen. */
if (vin > 0.0) cin = MassIn[n]/vin;
else cin = 0.0;
cmax = MAX(c, cin);
/* Mix inflow with tank contents */
if (vin > 0.0) c = (c*vold + cin*vin)/(vold + vin);
c = MIN(c, cmax);
c = MAX(c, 0.0);
Tank[i].C = c;
C[n] = Tank[i].C; C[n] = Tank[i].C;
} }
/*** Updated 10/25/00 ***/ /*** Updated 10/25/00 ***/
//// New version of tankmix2 //// //(2.00.12 - LR)
void tankmix2(int i, long dt) void tankmix2(int i, long dt)
/* /*
**------------------------------------------------ **------------------------------------------------
@@ -1045,11 +1095,11 @@ void tankmix2(int i, long dt)
*/ */
{ {
int k,n; int k,n;
long tstep, tstar; double cin, /* Inflow quality */
double cin, /* Inflow quality */ vin, /* Inflow volume */
qin, /* Inflow rate */ vt, /* Transferred volume */
qout, /* Outflow rate */ vnet, /* Net volume change */
qnet; /* Net flow rate */ v1max; /* Full mixing zone volume */
Pseg seg1,seg2; /* Compartment segments */ Pseg seg1,seg2; /* Compartment segments */
/* Identify segments for each compartment */ /* Identify segments for each compartment */
@@ -1058,88 +1108,64 @@ void tankmix2(int i, long dt)
seg2 = FirstSeg[k]; seg2 = FirstSeg[k];
if (seg1 == NULL || seg2 == NULL) return; if (seg1 == NULL || seg2 == NULL) return;
/* React contents of each compartment */
seg1->c = tankreact(seg1->c,seg1->v,Tank[i].Kb,dt);
seg2->c = tankreact(seg2->c,seg2->v,Tank[i].Kb,dt);
/* Find inflows & outflows */ /* Find inflows & outflows */
n = Tank[i].Node; n = Tank[i].Node;
qnet = D[n]; vnet = D[n]*dt;
qin = VolIn[n]/(double)dt; vin = VolIn[n];
qout = qin - qnet; if (vin > 0.0) cin = MassIn[n]/vin;
if (qin > 0.0) cin = MassIn[n]/VolIn[n];
else cin = 0.0; else cin = 0.0;
Tank[i].V += qnet*dt; v1max = Tank[i].V1max;
/* Case of no net volume change */ /* Tank is filling */
if (ABS(qnet) < TINY) vt = 0.0;
if (vnet > 0.0)
{ {
seg1->c = tankreact(seg1->c,seg1->v,Tank[i].Kb,dt); vt = MAX(0.0, (seg1->v + vnet - v1max));
seg2->c = tankreact(seg2->c,seg2->v,Tank[i].Kb,dt); if (vin > 0.0)
}
/* Case of net filling (qnet > 0) */
else if (qnet > 0.0)
{
/* Case where ambient zone empty & mixing zone filling */
if (seg2->v <= 0.0)
{ {
tstar = (long) ((Tank[i].V1max-(seg1->v))/qnet); seg1->c = ((seg1->c)*(seg1->v) + cin*vin) / (seg1->v + vin);
tstep = MIN(dt, tstar);
if (seg1->v > 0.0)
seg1->c = tankreact(seg1->c,seg1->v,Tank[i].Kb,tstep) +
qin*tstep*(cin-(seg1->c))/(seg1->v);
else seg1->c = cin;
seg1->c = MAX(0.0, seg1->c);
seg1->v += qnet*tstep;
seg2->c = 0.0;
dt -= tstep;
} }
if (vt > 0.0)
/* Case where mixing zone full & ambient zone filling */
if (dt > 1)
{ {
seg1->c = tankreact(seg1->c,seg1->v,Tank[i].Kb,dt) + seg2->c = ((seg2->c)*(seg2->v) + (seg1->c)*vt) / (seg2->v + vt);
qin*dt*(cin-(seg1->c))/(seg1->v);
seg1->c = MAX(0.0, seg1->c);
if (seg2->v <= 0.0) seg2->c = seg1->c;
else
seg2->c = tankreact(seg2->c,seg2->v,Tank[i].Kb,dt) +
qnet*dt*((seg1->c)-(seg2->c))/(seg2->v);
seg2->c = MAX(0.0, seg2->c);
seg2->v += qnet*dt;
}
}
/* Case of net emptying (qnet < 0) */
else if (qnet < 0.0 && seg1->v > 0.0)
{
/* Case where mixing zone full & ambient zone draining */
if ((seg2->v) > 0.0)
{
tstar = (long)(seg2->v/-qnet);
tstep = MIN(dt, tstar);
seg1->c = tankreact(seg1->c,seg1->v,Tank[i].Kb,tstep) +
(qin*cin - qnet*(seg2->c) - qout*(seg1->c))*
tstep/(seg1->v);
seg2->c = tankreact(seg2->c,seg2->v,Tank[i].Kb,tstep);
seg2->v += qnet*tstep;
seg1->c = MAX(0.0, seg1->c);
seg2->c = MAX(0.0, seg2->c);
seg2->v = MAX(0.0, seg2->v);
dt -= tstep;
}
/* Case where ambient zone empty & mixing zone draining */
if (dt > 1)
{
seg1->c = tankreact(seg1->c,seg1->v,Tank[i].Kb,dt) +
qin*dt*(cin-(seg1->c))/(seg1->v);
seg1->v += qnet*dt;
seg1->c = MAX(0.0, seg1->c);
seg1->v = MAX(0.0, seg1->v);
seg2->c = 0.0;
} }
} }
/* Tank is emptying */
if (vnet < 0.0)
{
if (seg2->v > 0.0)
{
vt = MIN(seg2->v, (-vnet));
}
if (vin + vt > 0.0)
{
seg1->c = ((seg1->c)*(seg1->v) + cin*vin + (seg2->c)*vt) /
(seg1->v + vin + vt);
}
}
/* Update segment volumes */
if (vt > 0.0)
{
seg1->v = v1max;
if (vnet > 0.0) seg2->v += vt;
else seg2->v = MAX(0.0, ((seg2->v)-vt));
}
else
{
seg1->v += vnet;
seg1->v = MIN(seg1->v, v1max);
seg1->v = MAX(0.0, seg1->v);
seg2->v = 0.0;
}
Tank[i].V += vnet;
Tank[i].V = MAX(0.0, Tank[i].V);
/* Use quality of mixed compartment (seg1) to */ /* Use quality of mixed compartment (seg1) to */
/* represent quality of tank since this is where */ /* represent quality of tank since this is where */
/* outflow begins to flow from */ /* outflow begins to flow from */
@@ -1185,6 +1211,7 @@ void tankmix3(int i, long dt)
if (vin > 0.0) cin = MassIn[n]/VolIn[n]; if (vin > 0.0) cin = MassIn[n]/VolIn[n];
else cin = 0.0; else cin = 0.0;
Tank[i].V += vnet; Tank[i].V += vnet;
Tank[i].V = MAX(0.0, Tank[i].V); //(2.00.12 - LR)
/* Withdraw flow from first segment */ /* Withdraw flow from first segment */
vsum = 0.0; vsum = 0.0;
@@ -1201,10 +1228,13 @@ void tankmix3(int i, long dt)
vout -= vseg; /* Remaining flow volume */ vout -= vseg; /* Remaining flow volume */
if (vout >= 0.0 && vseg >= seg->v) /* Seg used up */ if (vout >= 0.0 && vseg >= seg->v) /* Seg used up */
{ {
FirstSeg[k] = seg->prev; if (seg->prev) //(2.00.12 - LR)
if (FirstSeg[k] == NULL) LastSeg[k] = NULL; { //(2.00.12 - LR)
seg->prev = FreeSeg; FirstSeg[k] = seg->prev;
FreeSeg = seg; //if (FirstSeg[k] == NULL) LastSeg[k] = NULL; //(2.00.12 - LR)
seg->prev = FreeSeg;
FreeSeg = seg;
} //(2.00.12 - LR)
} }
else /* Remaining volume in segment */ else /* Remaining volume in segment */
{ {
@@ -1271,6 +1301,7 @@ void tankmix4(int i, long dt)
if (vin > 0.0) cin = MassIn[n]/VolIn[n]; if (vin > 0.0) cin = MassIn[n]/VolIn[n];
else cin = 0.0; else cin = 0.0;
Tank[i].V += vnet; Tank[i].V += vnet;
Tank[i].V = MAX(0.0, Tank[i].V); //(2.00.12 - LR)
Tank[i].C = LastSeg[k]->c; Tank[i].C = LastSeg[k]->c;
/* If tank filling, then create new last seg */ /* If tank filling, then create new last seg */
@@ -1317,10 +1348,13 @@ void tankmix4(int i, long dt)
vnet -= vseg; vnet -= vseg;
if (vnet >= 0.0 && vseg >= seg->v) /* Seg used up */ if (vnet >= 0.0 && vseg >= seg->v) /* Seg used up */
{ {
LastSeg[k] = seg->prev; if (seg->prev) //(2.00.12 - LR)
if (LastSeg[k] == NULL) FirstSeg[k] = NULL; { //(2.00.12 - LR)
seg->prev = FreeSeg; LastSeg[k] = seg->prev;
FreeSeg = seg; //if (LastSeg[k] == NULL) FirstSeg[k] = NULL; //(2.00.12 - LR)
seg->prev = FreeSeg;
FreeSeg = seg;
} //(2.00.12 - LR)
} }
else /* Remaining volume in segment */ else /* Remaining volume in segment */
{ {

View File

@@ -7,6 +7,7 @@ VERSION: 2.00
DATE: 5/30/00 DATE: 5/30/00
6/24/02 6/24/02
8/15/07 (2.00.11) 8/15/07 (2.00.11)
2/14/08 (2.00.12)
AUTHOR: L. Rossman AUTHOR: L. Rossman
US EPA - NRMRL US EPA - NRMRL
@@ -200,6 +201,14 @@ void writesummary()
writeline(s); writeline(s);
sprintf(s,FMT27,Hacc); sprintf(s,FMT27,Hacc);
writeline(s); writeline(s);
sprintf(s,FMT27a,CheckFreq); //(2.00.12 - LR)
writeline(s); //(2.00.12 - LR)
sprintf(s,FMT27b,MaxCheck); //(2.00.12 - LR)
writeline(s); //(2.00.12 - LR)
sprintf(s,FMT27c,DampLimit); //(2.00.12 - LR)
writeline(s); //(2.00.12 - LR)
sprintf(s,FMT28,MaxIter); sprintf(s,FMT28,MaxIter);
writeline(s); writeline(s);
if (Qualflag == NONE || Dur == 0.0) if (Qualflag == NONE || Dur == 0.0)
@@ -1210,5 +1219,4 @@ int getnodetype(int i)
return(2); return(2);
} }
/********************* END OF REPORT.C ********************/ /********************* END OF REPORT.C ********************/

View File

@@ -7,6 +7,7 @@ VERSION: 2.00
DATE: 5/8/00 DATE: 5/8/00
10/25/00 10/25/00
8/15/07 (2.00.11) 8/15/07 (2.00.11)
2/14/08 (2.00.12)
AUTHOR: L. Rossman AUTHOR: L. Rossman
US EPA - NRMRL US EPA - NRMRL
@@ -137,6 +138,7 @@ AUTHOR: L. Rossman
#define w_RQTOL "RQTOL" #define w_RQTOL "RQTOL"
#define w_CHECKFREQ "CHECKFREQ" #define w_CHECKFREQ "CHECKFREQ"
#define w_MAXCHECK "MAXCHECK" #define w_MAXCHECK "MAXCHECK"
#define w_DAMPLIMIT "DAMPLIMIT" //(2.00.12 - LR)
#define w_SECONDS "SEC" #define w_SECONDS "SEC"
#define w_MINUTES "MIN" #define w_MINUTES "MIN"
@@ -328,7 +330,7 @@ AUTHOR: L. Rossman
#define LOGO4 \ #define LOGO4 \
"* Analysis for Pipe Networks *" "* Analysis for Pipe Networks *"
#define LOGO5 \ #define LOGO5 \
"* Version 2.00.11 *" //(2.00.11 - LR) "* Version 2.00.12 *" //(2.00.12 - LR)
#define LOGO6 \ #define LOGO6 \
"******************************************************************" "******************************************************************"
#define FMT01 "\n... EPANET Version 2.0\n" #define FMT01 "\n... EPANET Version 2.0\n"
@@ -357,6 +359,11 @@ AUTHOR: L. Rossman
#define FMT25 " Headloss Formula .................. %s" #define FMT25 " Headloss Formula .................. %s"
#define FMT26 " Hydraulic Timestep ................ %-.2f %s" #define FMT26 " Hydraulic Timestep ................ %-.2f %s"
#define FMT27 " Hydraulic Accuracy ................ %-.6f" #define FMT27 " Hydraulic Accuracy ................ %-.6f"
#define FMT27a " Status Check Frequency ............ %-d" //(2.00.12 - LR)
#define FMT27b " Maximum Trials Checked ............ %-d" //(2.00.12 - LR)
#define FMT27c " Damping Limit Threshold ........... %-.6f" //(2.00.12 - LR)
#define FMT28 " Maximum Trials .................... %-d" #define FMT28 " Maximum Trials .................... %-d"
#define FMT29 " Quality Analysis .................. None" #define FMT29 " Quality Analysis .................. None"
#define FMT30 " Quality Analysis .................. %s" #define FMT30 " Quality Analysis .................. %s"
@@ -393,6 +400,10 @@ AUTHOR: L. Rossman
#define FMT57 " %s %s switched from %s to %s" #define FMT57 " %s %s switched from %s to %s"
#define FMT58 "%10s: Balanced after %-d trials" #define FMT58 "%10s: Balanced after %-d trials"
#define FMT59 "%10s: Unbalanced after %-d trials (flow change = %-.6f)" #define FMT59 "%10s: Unbalanced after %-d trials (flow change = %-.6f)"
#define FMT60a " Max. flow imbalance is %.4f %s at Node %s" //(2.00.12 - LR)
#define FMT60b " Max. head imbalance is %.4f %s at Link %s" //(2.00.12 - LR)
#define FMT61 "%10s: Valve %s caused ill-conditioning" #define FMT61 "%10s: Valve %s caused ill-conditioning"
#define FMT62 "%10s: System ill-conditioned at node %s" #define FMT62 "%10s: System ill-conditioned at node %s"
#define FMT63 "%10s: %s %s changed by rule %s" #define FMT63 "%10s: %s %s changed by rule %s"

View File

@@ -8,6 +8,7 @@ DATE: 5/8/00
10/25/00 10/25/00
3/1/01 3/1/01
8/15/07 (2.00.11) 8/15/07 (2.00.11)
2/14/08 (2.00.12)
AUTHOR: L. Rossman AUTHOR: L. Rossman
US EPA - NRMRL US EPA - NRMRL
@@ -50,6 +51,14 @@ AUTHOR: L. Rossman
#define EN_MIXMODEL 15 #define EN_MIXMODEL 15
#define EN_MIXZONEVOL 16 #define EN_MIXZONEVOL 16
#define EN_TANKDIAM 17
#define EN_MINVOLUME 18
#define EN_VOLCURVE 19
#define EN_MINLEVEL 20
#define EN_MAXLEVEL 21
#define EN_MIXFRACTION 22
#define EN_TANK_KBULK 23
#define EN_DIAMETER 0 /* Link parameters */ #define EN_DIAMETER 0 /* Link parameters */
#define EN_LENGTH 1 #define EN_LENGTH 1
#define EN_ROUGHNESS 2 #define EN_ROUGHNESS 2
@@ -134,6 +143,11 @@ AUTHOR: L. Rossman
#define EN_MAXIMUM 3 #define EN_MAXIMUM 3
#define EN_RANGE 4 #define EN_RANGE 4
#define EN_MIX1 0 /* Tank mixing models */
#define EN_MIX2 1
#define EN_FIFO 2
#define EN_LIFO 3
#define EN_NOSAVE 0 /* Save-results-to-file flag */ #define EN_NOSAVE 0 /* Save-results-to-file flag */
#define EN_SAVE 1 #define EN_SAVE 1
@@ -200,6 +214,7 @@ AUTHOR: L. Rossman
int DLLEXPORT ENsetcontrol(int, int, int, float, int, float); int DLLEXPORT ENsetcontrol(int, int, int, float, int, float);
int DLLEXPORT ENsetnodevalue(int, int, float); int DLLEXPORT ENsetnodevalue(int, int, float);
int DLLEXPORT ENsetlinkvalue(int, int, float); int DLLEXPORT ENsetlinkvalue(int, int, float);
int DLLEXPORT ENaddpattern(char *);
int DLLEXPORT ENsetpattern(int, float *, int); int DLLEXPORT ENsetpattern(int, float *, int);
int DLLEXPORT ENsetpatternvalue(int, int, float); int DLLEXPORT ENsetpatternvalue(int, int, float);
int DLLEXPORT ENsettimeparam(int, long); int DLLEXPORT ENsettimeparam(int, long);

View File

@@ -11,6 +11,7 @@ DATE: 5/8/00
12/6/01 12/6/01
6/24/02 6/24/02
8/15/07 (2.00.11) 8/15/07 (2.00.11)
2/14/08 (2.00.12)
AUTHOR: L. Rossman AUTHOR: L. Rossman
US EPA - NRMRL US EPA - NRMRL
@@ -20,6 +21,13 @@ AUTHOR: L. Rossman
/*********************************************************/ /*********************************************************/
/* All floats have been re-declared as doubles (7/3/07). */ /* All floats have been re-declared as doubles (7/3/07). */
/*********************************************************/ /*********************************************************/
/*
-------------------------------------------
Definition of 4-byte integers & reals
-------------------------------------------
*/
typedef float REAL4; //(2.00.11 - LR)
typedef int INT4; //(2.00.12 - LR)
/* /*
----------------------------- -----------------------------
@@ -27,7 +35,7 @@ AUTHOR: L. Rossman
----------------------------- -----------------------------
*/ */
/*** Updated ***/ /*** Updated ***/
#define CODEVERSION 20011 //(2.00.11 - LR) #define CODEVERSION 20012 //(2.00.12 - LR)
#define MAGICNUMBER 516114521 #define MAGICNUMBER 516114521
#define VERSION 200 #define VERSION 200
#define EOFMARK 0x1A /* Use 0x04 for UNIX systems */ #define EOFMARK 0x1A /* Use 0x04 for UNIX systems */
@@ -118,8 +126,6 @@ AUTHOR: L. Rossman
Global Data Structures Global Data Structures
------------------------------------------------------ ------------------------------------------------------
*/ */
typedef float REAL4; //(2.00.11 - LR)
typedef long INT4; //(2.00.11 - LR)
struct IDstring /* Holds component ID labels */ struct IDstring /* Holds component ID labels */
{ {

View File

@@ -5,6 +5,7 @@
VERSION: 2.00 VERSION: 2.00
DATE: 5/8/00 DATE: 5/8/00
6/24/02 6/24/02
2/14/08 (2.00.12)
AUTHOR: L. Rossman AUTHOR: L. Rossman
US EPA - NRMRL US EPA - NRMRL
@@ -25,6 +26,8 @@ EXTERN char Msg[MAXMSG+1], /* Text of output message */
HydFname[MAXFNAME+1], /* Hydraulics file name */ HydFname[MAXFNAME+1], /* Hydraulics file name */
OutFname[MAXFNAME+1], /* Binary output file name */ OutFname[MAXFNAME+1], /* Binary output file name */
MapFname[MAXFNAME+1], /* Map file name */ MapFname[MAXFNAME+1], /* Map file name */
TmpFname[MAXFNAME+1], /* Temporary file name */ //(2.00.12 - LR)
TmpDir[MAXFNAME+1], /* Temporary directory name */ //(2.00.12 - LR)
Title[MAXTITLE][MAXMSG+1], /* Problem title */ Title[MAXTITLE][MAXMSG+1], /* Problem title */
ChemName[MAXID+1], /* Name of chemical */ ChemName[MAXID+1], /* Name of chemical */
ChemUnits[MAXID+1], /* Units of chemical */ ChemUnits[MAXID+1], /* Units of chemical */
@@ -33,8 +36,10 @@ EXTERN char Msg[MAXMSG+1], /* Text of output message */
/*** Updated 6/24/02 ***/ /*** Updated 6/24/02 ***/
Atime[13], /* Clock time (hrs:min:sec) */ Atime[13], /* Clock time (hrs:min:sec) */
Outflag, /* Output file flag */ //(2.00.12 - LR)
Hydflag, /* Hydraulics flag */ Hydflag, /* Hydraulics flag */
Qualflag, /* Water quality flag */ Qualflag, /* Water quality flag */
Reactflag, /* Reaction indicator */ //(2.00.12 - LR)
Unitsflag, /* Unit system flag */ Unitsflag, /* Unit system flag */
Flowflag, /* Flow units flag */ Flowflag, /* Flow units flag */
Pressflag, /* Pressure units flag */ Pressflag, /* Pressure units flag */
@@ -95,6 +100,7 @@ EXTERN double Ucf[MAXVAR], /* Unit conversion factors */
Qexp, /* Exponent in orifice formula */ Qexp, /* Exponent in orifice formula */
Dmult, /* Demand multiplier */ Dmult, /* Demand multiplier */
Hacc, /* Hydraulics solution accuracy */ Hacc, /* Hydraulics solution accuracy */
DampLimit, /* Solution damping threshold */ //(2.00.12 - LR)
BulkOrder, /* Bulk flow reaction order */ BulkOrder, /* Bulk flow reaction order */
WallOrder, /* Pipe wall reaction order */ WallOrder, /* Pipe wall reaction order */
TankOrder, /* Tank reaction order */ TankOrder, /* Tank reaction order */