Merge branch 'dev' into issue-172
This commit is contained in:
@@ -9,6 +9,7 @@ env:
|
|||||||
before_install:
|
before_install:
|
||||||
- sudo apt-get -qq update
|
- sudo apt-get -qq update
|
||||||
- sudo apt-get install -y libboost-test-dev
|
- sudo apt-get install -y libboost-test-dev
|
||||||
|
- sudo apt-get install -y libboost-thread-dev
|
||||||
- sudo apt-get install -y swig
|
- sudo apt-get install -y swig
|
||||||
|
|
||||||
#install:
|
#install:
|
||||||
@@ -24,7 +25,7 @@ script:
|
|||||||
- cd tests
|
- cd tests
|
||||||
- ctest
|
- ctest
|
||||||
# run regression tests
|
# run regression tests
|
||||||
- cd $EPANET_HOME
|
#- cd $EPANET_HOME
|
||||||
- pip install -r tools/requirements.txt
|
#- pip install -r tools/requirements.txt
|
||||||
- tools/before-test.sh $TEST_HOME $EPANET_HOME/$BUILD_HOME/bin $TRAVIS_COMMIT
|
#- tools/before-test.sh $TEST_HOME $EPANET_HOME/$BUILD_HOME/bin $TRAVIS_COMMIT
|
||||||
- tools/run-nrtest.sh $TEST_HOME $TRAVIS_COMMIT
|
#- tools/run-nrtest.sh $TEST_HOME $TRAVIS_COMMIT
|
||||||
|
|||||||
@@ -75,12 +75,12 @@ source_group("Library" FILES ${EPANET_LIB_ALL})
|
|||||||
|
|
||||||
|
|
||||||
# the shared library
|
# the shared library
|
||||||
add_library(epanet SHARED ${EPANET_LIB_ALL}) #${EPANET_API_HEADER})
|
add_library(epanet SHARED ${EPANET_LIB_ALL})
|
||||||
target_include_directories(epanet PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
target_include_directories(epanet PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
|
||||||
# create export lib so we can link against dll using Visual Studio
|
# create export lib so we can link against dll using Visual Studio
|
||||||
add_definitions(-D WITH_GENX)
|
add_definitions(-DWITH_GENX)
|
||||||
include(GenerateExportHeader)
|
include(GenerateExportHeader)
|
||||||
GENERATE_EXPORT_HEADER(epanet
|
GENERATE_EXPORT_HEADER(epanet
|
||||||
BASE_NAME epanet
|
BASE_NAME epanet
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ EPANET {#epanet-readme}
|
|||||||
======
|
======
|
||||||
|
|
||||||
## Build Status
|
## Build Status
|
||||||
[](https://ci.appveyor.com/project/OpenWaterAnalytics/epanet)
|
[](https://ci.appveyor.com/project/OpenWaterAnalytics/epanet/branch/dev)
|
||||||
[](https://travis-ci.org/OpenWaterAnalytics/EPANET)
|
[](https://travis-ci.org/OpenWaterAnalytics/EPANET)
|
||||||
|
|
||||||
## For EPANET-related questions and discussion
|
## For EPANET-related questions and discussion
|
||||||
For community discussion, FAQ, and roadmapping of the project, go to the [Community Forum](http://community.wateranalytics.org/category/epanet).
|
For community discussion, FAQ, and roadmapping of the project, go to the [Community Forum](http://community.wateranalytics.org/category/epanet).
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Release Notes for EPANET 2.2 (Draft)
|
Release Notes for EPANET 2.2 (Draft)
|
||||||
============================
|
============================
|
||||||
|
|
||||||
@@ -49,15 +47,18 @@ These new parameters augment the current `EN_ACCURACY` option which always remai
|
|||||||
## Improved Linear Solver Routine
|
## Improved Linear Solver Routine
|
||||||
EPANET's hydraulic solver requires solving a system of linear equations over a series of iterations until a set of convergence criteria are met. The coefficient matrix of this linear system is square and symmetric. It has a row for each network node and a non-zero off-diagonal coefficient for each link. The numerical effort needed to solve the linear system can be reduced if the nodes are re-ordered so that the non-zero coefficients cluster more tightly around the diagonal.
|
EPANET's hydraulic solver requires solving a system of linear equations over a series of iterations until a set of convergence criteria are met. The coefficient matrix of this linear system is square and symmetric. It has a row for each network node and a non-zero off-diagonal coefficient for each link. The numerical effort needed to solve the linear system can be reduced if the nodes are re-ordered so that the non-zero coefficients cluster more tightly around the diagonal.
|
||||||
|
|
||||||
EPANET's original node re-ordering scheme has been replaced by the more powerful **Multiple Minimum Degree (MMD)** algorithm. On a series of eight networks ranging in size from 7,700 to 100,000 nodes **MMD** reduced the solution time for a single period (steady state) hydraulic analysis by an average of more than 50%.
|
EPANET's original node re-ordering scheme has been replaced by the more powerful **Multiple Minimum Degree (MMD)** algorithm. On a series of eight networks ranging in size from 7,700 to 100,000 nodes **MMD** reduced the solution time for a single period (steady state) hydraulic analysis by an average of 58%.
|
||||||
|
|
||||||
## Pressure Dependent Demands
|
## Pressure Dependent Demands
|
||||||
EPANET has always employed a Demand Driven Analysis (**DDA**) when modeling network hydraulics. Under this approach nodal demands at a given point in time are fixed values that must be delivered no matter what nodal heads and link flows are produced by a hydraulic solution. This can result in situations where required demands are satisfied at nodes that have negative pressures - a physical impossibility.
|
EPANET has always employed a Demand Driven Analysis (**DDA**) when modeling network hydraulics. Under this approach nodal demands at a given point in time are fixed values that must be delivered no matter what nodal heads and link flows are produced by a hydraulic solution. This can result in situations where required demands are satisfied at nodes that have negative pressures - a physical impossibility.
|
||||||
|
|
||||||
To address this issue EPANET has been extended to use a Pressure Driven Analysis (**PDA**) if so desired. Under **PDA**, the demand *D* delivered at a node depends on the node's available pressure *P* according to:
|
To address this issue EPANET has been extended to use a Pressure Driven Analysis (**PDA**) if so desired. Under **PDA**, the demand *D* delivered at a node depends on the node's available pressure *P* according to:
|
||||||
$$D =D_f\left(\frac{P-P_{min}}{P_{req}-P_{min}}\right)^{P_{exp}} for P_{0}<=P<=P_{req}$$where *D<sub>f</sub>* is the full demand required, *P<sub>min</sub>* is the pressure below which demand is zero, *P<sub>req</sub>* is the pressure required to deliver the full required demand and *P<sub>exp</sub>* is an exponent. When *P < P<sub>min</sub>* demand is 0 and when *P > P<sub>req</sub>* demand equals *D<sub>f</sub>*.
|
|
||||||
|
|
||||||
To implement pressure dependent analysis four new parameters have been added to the [OPTIONS] section of the EPANET input file:
|
*D = D<sub>f</sub> [ (P - P<sub>min</sub>) / (P<sub>req</sub> - P<sub>min</sub>) ]<sup>P<sub>exp</sub></sup>*
|
||||||
|
|
||||||
|
where *D<sub>f</sub>* is the full demand required, *P<sub>min</sub>* is the pressure below which demand is zero, *P<sub>req</sub>* is the pressure required to deliver the full required demand and *P<sub>exp</sub>* is an exponent. When *P < P<sub>min</sub>* demand is 0 and when *P > P<sub>req</sub>* demand equals *D<sub>f</sub>*.
|
||||||
|
|
||||||
|
To implement pressure driven analysis four new parameters have been added to the [OPTIONS] section of the EPANET input file:
|
||||||
|
|
||||||
|
|
||||||
| Parameter | Description | Default |
|
| Parameter | Description | Default |
|
||||||
@@ -81,7 +82,8 @@ for the thread-safe API. Some additional points regarding the new **PDA** option
|
|||||||
|
|
||||||
- If no DEMAND MODEL and its parameters are specified then the analysis defaults to being demand driven (**DDA**).
|
- If no DEMAND MODEL and its parameters are specified then the analysis defaults to being demand driven (**DDA**).
|
||||||
- This implementation of **PDA** assumes that the same parameters apply to all nodes in the network. Extending the framework to allow different parameters for specific nodes is straightforward to do but is left as a future feature to implement.
|
- This implementation of **PDA** assumes that the same parameters apply to all nodes in the network. Extending the framework to allow different parameters for specific nodes is straightforward to do but is left as a future feature to implement.
|
||||||
- *P<sub>0</sub>* is allowed to equal to *P<sub>req</sub>*. This condition can be used to find a solution that results in the smallest amount of demand reductions needed to insure that no node delivers positive demand at a pressure below *P<sub>min</min>*.
|
- *P<sub>min</sub>* is allowed to equal to *P<sub>req</sub>*. This condition can be used to find a solution that results in the smallest amount of demand reductions needed to insure that no node delivers positive demand at a pressure below *P<sub>min</min>*.
|
||||||
|
|
||||||
|
|
||||||
## Code Changes
|
## Code Changes
|
||||||
|
|
||||||
|
|||||||
@@ -254,6 +254,7 @@ Public Const EN_G_CURVE = 4 ' General\default curve
|
|||||||
Declare Function ENsetqualtype Lib "epanet2.dll" (ByVal QualCode As Long, ByVal ChemName As String, ByVal ChemUnits As String, ByVal TraceNode As String) As Long
|
Declare Function ENsetqualtype Lib "epanet2.dll" (ByVal QualCode As Long, ByVal ChemName As String, ByVal ChemUnits As String, ByVal TraceNode As String) As Long
|
||||||
Declare Function ENgetqualinfo Lib "epanet2.dll" (QualCode As Long, ByVal ChemName As String, ByVal ChemUnits As String, TraceNode As Long) As Long
|
Declare Function ENgetqualinfo Lib "epanet2.dll" (QualCode As Long, ByVal ChemName As String, ByVal ChemUnits As String, TraceNode As Long) As Long
|
||||||
Declare Function ENsetbasedemand Lib "epanet2.dll" (ByVal nodeIndex As Long, ByVal DemandIndex As Long, ByVal BaseDemand As Single) As Long
|
Declare Function ENsetbasedemand Lib "epanet2.dll" (ByVal nodeIndex As Long, ByVal DemandIndex As Long, ByVal BaseDemand As Single) As Long
|
||||||
|
Declare Function ENsetdemandpattern Lib "epanet2.dll" (ByVal Index As Long, ByVal DemandIndex As Long, ByVal PatIndex As Long) As Long
|
||||||
|
|
||||||
Declare Function ENgetcurveindex Lib "epanet2.dll" (ByVal id As String, index As Long) As Long
|
Declare Function ENgetcurveindex Lib "epanet2.dll" (ByVal id As String, index As Long) As Long
|
||||||
Declare Function ENgetcurveid Lib "epanet2.dll" (ByVal index As Long, ByVal id As String) As Long
|
Declare Function ENgetcurveid Lib "epanet2.dll" (ByVal index As Long, ByVal id As String) As Long
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_GENX
|
#ifdef WITH_GENX
|
||||||
#include "epanet_export.h"
|
#include "epanet_export.h"
|
||||||
#else
|
#else
|
||||||
// --- define WINDOWS
|
// --- define WINDOWS
|
||||||
#undef WINDOWS
|
#undef WINDOWS
|
||||||
@@ -1171,12 +1171,15 @@ extern "C" {
|
|||||||
int DLLEXPORT EN_createproject(EN_ProjectHandle *ph);
|
int DLLEXPORT EN_createproject(EN_ProjectHandle *ph);
|
||||||
int DLLEXPORT EN_deleteproject(EN_ProjectHandle *ph);
|
int DLLEXPORT EN_deleteproject(EN_ProjectHandle *ph);
|
||||||
|
|
||||||
|
int DLLEXPORT EN_runproject(EN_ProjectHandle ph, const char *f1,
|
||||||
|
const char *f2, const char *f3, void (*pviewprog)(char *));
|
||||||
|
|
||||||
void DLLEXPORT EN_clearError(EN_ProjectHandle ph);
|
void DLLEXPORT EN_clearError(EN_ProjectHandle ph);
|
||||||
int DLLEXPORT EN_checkError(EN_ProjectHandle ph, char** msg_buffer);
|
int DLLEXPORT EN_checkError(EN_ProjectHandle ph, char** msg_buffer);
|
||||||
|
|
||||||
//int DLLEXPORT EN_epanet(EN_ProjectHandle ph, const char *f1, const char *f2,
|
//int DLLEXPORT EN_epanet(EN_ProjectHandle ph, const char *f1, const char *f2,
|
||||||
// const char *f3, void(*pviewprog)(char *));
|
// const char *f3, void(*pviewprog)(char *));
|
||||||
int DLLEXPORT EN_init(EN_ProjectHandle *ph, char *rptFile, char *binOutFile,
|
int DLLEXPORT EN_init(EN_ProjectHandle ph, char *rptFile, char *binOutFile,
|
||||||
EN_FlowUnits UnitsType, EN_FormType HeadlossFormula);
|
EN_FlowUnits UnitsType, EN_FormType HeadlossFormula);
|
||||||
|
|
||||||
int DLLEXPORT EN_open(EN_ProjectHandle ph, const char *inpFile,
|
int DLLEXPORT EN_open(EN_ProjectHandle ph, const char *inpFile,
|
||||||
@@ -1265,6 +1268,7 @@ extern "C" {
|
|||||||
|
|
||||||
int DLLEXPORT EN_getqualinfo(EN_ProjectHandle ph, int *qualcode, char *chemname, char *chemunits, int *tracenode);
|
int DLLEXPORT EN_getqualinfo(EN_ProjectHandle ph, int *qualcode, char *chemname, char *chemunits, int *tracenode);
|
||||||
int DLLEXPORT EN_setbasedemand(EN_ProjectHandle ph, int nodeIndex, int demandIdx, EN_API_FLOAT_TYPE baseDemand);
|
int DLLEXPORT EN_setbasedemand(EN_ProjectHandle ph, int nodeIndex, int demandIdx, EN_API_FLOAT_TYPE baseDemand);
|
||||||
|
int DLLEXPORT EN_setdemandpattern(EN_ProjectHandle ph, int nodeIndex, int demandIdx, int patIndex);
|
||||||
int DLLEXPORT EN_getcurveindex(EN_ProjectHandle ph, char *id, int *index);
|
int DLLEXPORT EN_getcurveindex(EN_ProjectHandle ph, char *id, int *index);
|
||||||
int DLLEXPORT EN_getcurveid(EN_ProjectHandle ph, int index, char *id);
|
int DLLEXPORT EN_getcurveid(EN_ProjectHandle ph, int index, char *id);
|
||||||
int DLLEXPORT EN_getcurvelen(EN_ProjectHandle ph, int index, int *len);
|
int DLLEXPORT EN_getcurvelen(EN_ProjectHandle ph, int index, int *len);
|
||||||
|
|||||||
@@ -197,8 +197,10 @@ Public Const EN_CUSTOM = 2 ' user-defined custom curve
|
|||||||
Declare Function ENsetcoord Lib "epanet2.dll" (ByVal Index As Int32, ByVal X As Single, ByVal Y As Single) As Int32
|
Declare Function ENsetcoord Lib "epanet2.dll" (ByVal Index As Int32, ByVal X As Single, ByVal Y As Single) As Int32
|
||||||
|
|
||||||
Declare Function ENgetnumdemands Lib "epanet2.dll" (ByVal Index As Int32, ByRef numDemands As Int32) As Int32 'ES
|
Declare Function ENgetnumdemands Lib "epanet2.dll" (ByVal Index As Int32, ByRef numDemands As Int32) As Int32 'ES
|
||||||
Declare Function ENgetbasedemand Lib "epanet2.dll" (ByVal Index As Int32, ByVal DemandIndex As Int32, ByRef Value As Single) As Int32 'ES
|
Declare Function ENgetbasedemand Lib "epanet2.dll" (ByVal Index As Int32, ByVal DemandIndex As Int32, ByRef BaseDemand As Single) As Int32 'ES
|
||||||
|
Declare Function ENsetbasedemand Lib "epanet2.dll" (ByVal Index As Int32, ByVal DemandIndex As Int32, ByVal BaseDemand As Single) As Int32 'ES
|
||||||
Declare Function ENgetdemandpattern Lib "epanet2.dll" (ByVal Index As Int32, ByVal DemandIndex As Int32, ByRef PatIndex As Int32) As Int32 'ES
|
Declare Function ENgetdemandpattern Lib "epanet2.dll" (ByVal Index As Int32, ByVal DemandIndex As Int32, ByRef PatIndex As Int32) As Int32 'ES
|
||||||
|
Declare Function ENsetdemandpattern Lib "epanet2.dll" (ByVal Index As Int32, ByVal DemandIndex As Int32, ByVal PatIndex As Int32) As Int32 'ES
|
||||||
|
|
||||||
Declare Function ENgetlinkindex Lib "epanet2.dll" (ByVal ID As String, ByRef Index As Int32) As Int32
|
Declare Function ENgetlinkindex Lib "epanet2.dll" (ByVal ID As String, ByRef Index As Int32) As Int32
|
||||||
Declare Function ENgetlinkid Lib "epanet2.dll" (ByVal Index As Int32, ByVal ID As StringBuilder) As Int32
|
Declare Function ENgetlinkid Lib "epanet2.dll" (ByVal Index As Int32, ByVal ID As StringBuilder) As Int32
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ include_directories(include)
|
|||||||
|
|
||||||
source_group("CLI" FILES ${EPANET_CLI_SOURCES})
|
source_group("CLI" FILES ${EPANET_CLI_SOURCES})
|
||||||
|
|
||||||
|
add_definitions(-DWITH_GENX)
|
||||||
|
|
||||||
# Creates the EPANET command line executable
|
# Creates the EPANET command line executable
|
||||||
add_definitions(-D WITH_GENX)
|
|
||||||
add_executable(runepanet ${EPANET_CLI_SOURCES})
|
add_executable(runepanet ${EPANET_CLI_SOURCES})
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
target_link_libraries(runepanet LINK_PUBLIC epanet m)
|
target_link_libraries(runepanet LINK_PUBLIC epanet m)
|
||||||
|
|||||||
98
src/epanet.c
98
src/epanet.c
@@ -132,7 +132,7 @@ execute function x and set the error code equal to its return value.
|
|||||||
|
|
||||||
// This single global variable is used only when the library is called
|
// This single global variable is used only when the library is called
|
||||||
// in "legacy mode" with the 2.1-style API.
|
// in "legacy mode" with the 2.1-style API.
|
||||||
EN_Project *_defaultModel;
|
void *_defaultModel;
|
||||||
|
|
||||||
|
|
||||||
// Local functions
|
// Local functions
|
||||||
@@ -164,12 +164,15 @@ void errorLookup(int errcode, char *errmsg, int len);
|
|||||||
int DLLEXPORT ENepanet(const char *f1, const char *f2, const char *f3, void (*pviewprog)(char *))
|
int DLLEXPORT ENepanet(const char *f1, const char *f2, const char *f3, void (*pviewprog)(char *))
|
||||||
{
|
{
|
||||||
int errcode = 0;
|
int errcode = 0;
|
||||||
|
EN_Project *p = NULL;
|
||||||
|
|
||||||
ERRCODE(EN_createproject(&_defaultModel));
|
ERRCODE(EN_createproject(&_defaultModel));
|
||||||
ERRCODE(EN_open(_defaultModel, f1, f2, f3));
|
ERRCODE(EN_open(_defaultModel, f1, f2, f3));
|
||||||
_defaultModel->viewprog = pviewprog;
|
|
||||||
|
|
||||||
if (_defaultModel->out_files.Hydflag != USE) {
|
p = (EN_Project*)(_defaultModel);
|
||||||
|
p->viewprog = pviewprog;
|
||||||
|
|
||||||
|
if (p->out_files.Hydflag != USE) {
|
||||||
ERRCODE(EN_solveH(_defaultModel));
|
ERRCODE(EN_solveH(_defaultModel));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,6 +185,14 @@ int DLLEXPORT ENepanet(const char *f1, const char *f2, const char *f3, void (*pv
|
|||||||
return (errcode);
|
return (errcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DLLEXPORT ENinit(char *f2, char *f3, int UnitsType,
|
||||||
|
int HeadlossFormula) {
|
||||||
|
int errcode = 0;
|
||||||
|
ERRCODE(EN_createproject(&_defaultModel));
|
||||||
|
ERRCODE(EN_init(_defaultModel, f2, f3, UnitsType, HeadlossFormula));
|
||||||
|
return (errcode);
|
||||||
|
}
|
||||||
|
|
||||||
int DLLEXPORT ENopen(char *f1, char *f2, char *f3) {
|
int DLLEXPORT ENopen(char *f1, char *f2, char *f3) {
|
||||||
int errcode = 0;
|
int errcode = 0;
|
||||||
ERRCODE(EN_createproject(&_defaultModel));
|
ERRCODE(EN_createproject(&_defaultModel));
|
||||||
@@ -473,6 +484,10 @@ int DLLEXPORT ENsetbasedemand(int nodeIndex, int demandIdx,
|
|||||||
return EN_setbasedemand(_defaultModel, nodeIndex, demandIdx, baseDemand);
|
return EN_setbasedemand(_defaultModel, nodeIndex, demandIdx, baseDemand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DLLEXPORT ENsetdemandpattern(int nodeIndex, int demandIdx, int patIndex) {
|
||||||
|
return EN_setdemandpattern(_defaultModel, nodeIndex, demandIdx, patIndex);
|
||||||
|
}
|
||||||
|
|
||||||
int DLLEXPORT ENgetdemandpattern(int nodeIndex, int demandIdx, int *pattIdx) {
|
int DLLEXPORT ENgetdemandpattern(int nodeIndex, int demandIdx, int *pattIdx) {
|
||||||
return EN_getdemandpattern(_defaultModel, nodeIndex, demandIdx, pattIdx);
|
return EN_getdemandpattern(_defaultModel, nodeIndex, demandIdx, pattIdx);
|
||||||
}
|
}
|
||||||
@@ -598,8 +613,29 @@ int DLLEXPORT EN_deleteproject(EN_ProjectHandle *ph)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DLLEXPORT EN_runproject(EN_ProjectHandle ph, const char *f1, const char *f2,
|
||||||
|
const char *f3, void (*pviewprog)(char *))
|
||||||
|
{
|
||||||
|
int errcode = 0;
|
||||||
|
EN_Project *p = NULL;
|
||||||
|
|
||||||
int DLLEXPORT EN_init(EN_ProjectHandle *ph, char *f2, char *f3,
|
ERRCODE(EN_open(ph, f1, f2, f3));
|
||||||
|
p = (EN_Project*)(ph);
|
||||||
|
p->viewprog = pviewprog;
|
||||||
|
|
||||||
|
if (p->out_files.Hydflag != USE) {
|
||||||
|
ERRCODE(EN_solveH(ph));
|
||||||
|
}
|
||||||
|
|
||||||
|
ERRCODE(EN_solveQ(ph));
|
||||||
|
ERRCODE(EN_report(ph));
|
||||||
|
|
||||||
|
EN_close(ph);
|
||||||
|
|
||||||
|
return errcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DLLEXPORT EN_init(EN_ProjectHandle ph, char *f2, char *f3,
|
||||||
EN_FlowUnits UnitsType, EN_FormType HeadlossFormula)
|
EN_FlowUnits UnitsType, EN_FormType HeadlossFormula)
|
||||||
/*----------------------------------------------------------------
|
/*----------------------------------------------------------------
|
||||||
** Input:
|
** Input:
|
||||||
@@ -620,7 +656,7 @@ int DLLEXPORT EN_init(EN_ProjectHandle *ph, char *f2, char *f3,
|
|||||||
_fpreset();
|
_fpreset();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EN_Project *pr = (EN_Project*)*ph;
|
EN_Project *pr = (EN_Project*)ph;
|
||||||
|
|
||||||
/* Set system flags */
|
/* Set system flags */
|
||||||
pr->Openflag = TRUE;
|
pr->Openflag = TRUE;
|
||||||
@@ -3100,7 +3136,7 @@ int DLLEXPORT EN_addpattern(EN_ProjectHandle ph, char *id) {
|
|||||||
|
|
||||||
if (!p->Openflag)
|
if (!p->Openflag)
|
||||||
return set_error(p->error_handle, 102);
|
return set_error(p->error_handle, 102);
|
||||||
if (ENgetpatternindex(id, &i) == 0)
|
if (EN_getpatternindex(ph, id, &i) == 0)
|
||||||
return set_error(p->error_handle, 215);
|
return set_error(p->error_handle, 215);
|
||||||
|
|
||||||
/* Check that id name is not too long */
|
/* Check that id name is not too long */
|
||||||
@@ -3153,7 +3189,7 @@ int DLLEXPORT EN_addpattern(EN_ProjectHandle ph, char *id) {
|
|||||||
for (i = 0; i <= Npats; i++)
|
for (i = 0; i <= Npats; i++)
|
||||||
free(Pattern[i].F);
|
free(Pattern[i].F);
|
||||||
free(Pattern);
|
free(Pattern);
|
||||||
Pattern = tmpPat;
|
net->Pattern = tmpPat;
|
||||||
net->Npats = n;
|
net->Npats = n;
|
||||||
par->MaxPats = n;
|
par->MaxPats = n;
|
||||||
return set_error(p->error_handle, 0);
|
return set_error(p->error_handle, 0);
|
||||||
@@ -4474,7 +4510,7 @@ int DLLEXPORT EN_getbasedemand(EN_ProjectHandle ph, int nodeIndex, int demandIdx
|
|||||||
if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes)
|
if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes)
|
||||||
return set_error(p->error_handle, 203);
|
return set_error(p->error_handle, 203);
|
||||||
if (nodeIndex <= p->network.Njuncs) {
|
if (nodeIndex <= p->network.Njuncs) {
|
||||||
for (d = p->network.Node[nodeIndex].D; n < demandIdx && d != NULL; d = d->next) {
|
for (d = p->network.Node[nodeIndex].D; n < demandIdx && d->next != NULL; d = d->next) {
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
if (n != demandIdx) {
|
if (n != demandIdx) {
|
||||||
@@ -4507,7 +4543,7 @@ int DLLEXPORT EN_setbasedemand(EN_ProjectHandle ph, int nodeIndex, int demandIdx
|
|||||||
if (nodeIndex <= 0 || nodeIndex > Nnodes)
|
if (nodeIndex <= 0 || nodeIndex > Nnodes)
|
||||||
return set_error(pr->error_handle, 203);
|
return set_error(pr->error_handle, 203);
|
||||||
if (nodeIndex <= Njuncs) {
|
if (nodeIndex <= Njuncs) {
|
||||||
for (d = Node[nodeIndex].D; n < demandIdx && d != NULL; d = d->next)
|
for (d = Node[nodeIndex].D; n < demandIdx && d->next != NULL; d = d->next)
|
||||||
n++;
|
n++;
|
||||||
if (n != demandIdx)
|
if (n != demandIdx)
|
||||||
return set_error(pr->error_handle, 253);
|
return set_error(pr->error_handle, 253);
|
||||||
@@ -4516,6 +4552,36 @@ int DLLEXPORT EN_setbasedemand(EN_ProjectHandle ph, int nodeIndex, int demandIdx
|
|||||||
return set_error(pr->error_handle, 0);
|
return set_error(pr->error_handle, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DLLEXPORT EN_setdemandpattern(EN_ProjectHandle ph, int nodeIndex, int demandIdx, int patIndex) {
|
||||||
|
|
||||||
|
EN_Project *pr = (EN_Project*)ph;
|
||||||
|
|
||||||
|
EN_Network *net = &pr->network;
|
||||||
|
Snode *Node = net->Node;
|
||||||
|
|
||||||
|
const int Nnodes = net->Nnodes;
|
||||||
|
const int Njuncs = net->Njuncs;
|
||||||
|
const int Npats = net->Npats;
|
||||||
|
|
||||||
|
Pdemand d;
|
||||||
|
int n = 1;
|
||||||
|
/* Check for valid arguments */
|
||||||
|
if (!pr->Openflag)
|
||||||
|
return set_error(pr->error_handle, 102);
|
||||||
|
if (nodeIndex <= 0 || nodeIndex > Nnodes)
|
||||||
|
return set_error(pr->error_handle, 203);
|
||||||
|
if (patIndex < 1 || patIndex > Npats)
|
||||||
|
return(205);
|
||||||
|
if (nodeIndex <= Njuncs) {
|
||||||
|
for (d = Node[nodeIndex].D; n < demandIdx && d->next != NULL; d = d->next)
|
||||||
|
n++;
|
||||||
|
if (n != demandIdx)
|
||||||
|
return set_error(pr->error_handle, 253);
|
||||||
|
d->Pat = patIndex;
|
||||||
|
}
|
||||||
|
return set_error(pr->error_handle, 0);
|
||||||
|
}
|
||||||
|
|
||||||
int DLLEXPORT EN_getdemandpattern(EN_ProjectHandle ph, int nodeIndex, int demandIdx, int *pattIdx) {
|
int DLLEXPORT EN_getdemandpattern(EN_ProjectHandle ph, int nodeIndex, int demandIdx, int *pattIdx) {
|
||||||
|
|
||||||
EN_Project *p = (EN_Project*)ph;
|
EN_Project *p = (EN_Project*)ph;
|
||||||
@@ -4531,7 +4597,7 @@ int DLLEXPORT EN_getdemandpattern(EN_ProjectHandle ph, int nodeIndex, int demand
|
|||||||
return set_error(p->error_handle, 102);
|
return set_error(p->error_handle, 102);
|
||||||
if (nodeIndex <= 0 || nodeIndex > Nnodes)
|
if (nodeIndex <= 0 || nodeIndex > Nnodes)
|
||||||
return set_error(p->error_handle, 203);
|
return set_error(p->error_handle, 203);
|
||||||
for (d = Node[nodeIndex].D; n < demandIdx && d != NULL; d = d->next)
|
for (d = Node[nodeIndex].D; n < demandIdx && d->next != NULL; d = d->next)
|
||||||
n++;
|
n++;
|
||||||
if (n != demandIdx)
|
if (n != demandIdx)
|
||||||
return set_error(p->error_handle, 253);
|
return set_error(p->error_handle, 253);
|
||||||
@@ -4846,6 +4912,7 @@ int DLLEXPORT EN_addlink(EN_ProjectHandle ph, char *id, EN_LinkType linkType, ch
|
|||||||
link->Type = linkType;
|
link->Type = linkType;
|
||||||
link->N1 = N1;
|
link->N1 = N1;
|
||||||
link->N2 = N2;
|
link->N2 = N2;
|
||||||
|
link->Stat = OPEN;
|
||||||
|
|
||||||
if (linkType == EN_PUMP) {
|
if (linkType == EN_PUMP) {
|
||||||
link->Kc = 1.0; // Speed factor
|
link->Kc = 1.0; // Speed factor
|
||||||
@@ -4861,23 +4928,14 @@ int DLLEXPORT EN_addlink(EN_ProjectHandle ph, char *id, EN_LinkType linkType, ch
|
|||||||
link->Kc = 0.0; // Valve setting.
|
link->Kc = 0.0; // Valve setting.
|
||||||
link->Km = 0.0; // Loss coeff
|
link->Km = 0.0; // Loss coeff
|
||||||
link->Len = 0.0;
|
link->Len = 0.0;
|
||||||
|
link->Stat = ACTIVE;
|
||||||
}
|
}
|
||||||
// link->Len = 0.0;
|
|
||||||
// link->Kc = 0.01;
|
|
||||||
// link->Km = 0;
|
|
||||||
link->Kb = 0;
|
link->Kb = 0;
|
||||||
link->Kw = 0;
|
link->Kw = 0;
|
||||||
link->R = 0;
|
link->R = 0;
|
||||||
link->Rc = 0;
|
link->Rc = 0;
|
||||||
link->Rpt = 0;
|
link->Rpt = 0;
|
||||||
|
|
||||||
if (linkType == EN_CVPIPE) {
|
|
||||||
link->Stat = OPEN;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
link->Stat = CLOSED;
|
|
||||||
}
|
|
||||||
|
|
||||||
ENHashTableInsert(net->LinkHashTable, link->ID, n);
|
ENHashTableInsert(net->LinkHashTable, link->ID, n);
|
||||||
return set_error(p->error_handle, 0);
|
return set_error(p->error_handle, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
240
src/mempool.c
240
src/mempool.c
@@ -1,17 +1,9 @@
|
|||||||
/* mempool.c
|
/* mempool.c
|
||||||
**
|
**
|
||||||
** A simple fast memory allocation package.
|
** A simple fast pooled memory allocation package.
|
||||||
**
|
**
|
||||||
** By Steve Hill in Graphics Gems III, David Kirk (ed.),
|
** Based on code by Steve Hill in Graphics Gems III,
|
||||||
** Academic Press, Boston, MA, 1992
|
** David Kirk (ed.), Academic Press, Boston, MA, 1992
|
||||||
**
|
|
||||||
** Modified by Lew Rossman, 8/13/94.
|
|
||||||
**
|
|
||||||
** AllocInit() - create an alloc pool, returns the old pool handle
|
|
||||||
** Alloc() - allocate memory
|
|
||||||
** AllocReset() - reset the current pool
|
|
||||||
** AllocSetPool() - set the current pool
|
|
||||||
** AllocFree() - free the memory used by the current pool.
|
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -28,95 +20,80 @@
|
|||||||
|
|
||||||
#define ALLOC_BLOCK_SIZE 64000 /*(62*1024)*/
|
#define ALLOC_BLOCK_SIZE 64000 /*(62*1024)*/
|
||||||
|
|
||||||
/*
|
struct MemBlock
|
||||||
** alloc_hdr_t - Header for each block of memory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct alloc_hdr_s
|
|
||||||
{
|
{
|
||||||
struct alloc_hdr_s *next; /* Next Block */
|
struct MemBlock *next; // Next block
|
||||||
char *block, /* Start of block */
|
char *block, // Start of block
|
||||||
*free, /* Next free in block */
|
*free, // Next free position in block
|
||||||
*end; /* block + block size */
|
*end; // block + block size
|
||||||
} alloc_hdr_t;
|
};
|
||||||
|
|
||||||
/*
|
struct Mempool
|
||||||
** alloc_root_t - Header for the whole pool.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct alloc_root_s
|
|
||||||
{
|
{
|
||||||
alloc_hdr_t *first, /* First header in pool */
|
struct MemBlock *first;
|
||||||
*current; /* Current header */
|
struct MemBlock *current;
|
||||||
} alloc_root_t;
|
};
|
||||||
|
|
||||||
/*
|
static struct MemBlock* createMemBlock()
|
||||||
** root - Pointer to the current pool.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static alloc_root_t *root;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** AllocHdr()
|
|
||||||
**
|
|
||||||
** Private routine to allocate a header and memory block.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static alloc_hdr_t *AllocHdr(void);
|
|
||||||
|
|
||||||
static alloc_hdr_t * AllocHdr()
|
|
||||||
{
|
{
|
||||||
alloc_hdr_t *hdr;
|
struct MemBlock* memBlock = malloc(sizeof(struct MemBlock));
|
||||||
char *block;
|
if (memBlock)
|
||||||
|
{
|
||||||
block = (char *) malloc(ALLOC_BLOCK_SIZE);
|
memBlock->block = malloc(ALLOC_BLOCK_SIZE * sizeof(char));
|
||||||
hdr = (alloc_hdr_t *) malloc(sizeof(alloc_hdr_t));
|
if (memBlock->block == NULL)
|
||||||
|
{
|
||||||
if (hdr == NULL || block == NULL) return(NULL);
|
free(memBlock);
|
||||||
hdr->block = block;
|
return NULL;
|
||||||
hdr->free = block;
|
}
|
||||||
hdr->next = NULL;
|
memBlock->free = memBlock->block;
|
||||||
hdr->end = block + ALLOC_BLOCK_SIZE;
|
memBlock->next = NULL;
|
||||||
|
memBlock->end = memBlock->block + ALLOC_BLOCK_SIZE;
|
||||||
return(hdr);
|
}
|
||||||
|
return memBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
static void deleteMemBlock(struct MemBlock* memBlock)
|
||||||
** AllocInit()
|
|
||||||
**
|
|
||||||
** Create a new memory pool with one block.
|
|
||||||
** Returns pointer to the new pool.
|
|
||||||
*/
|
|
||||||
|
|
||||||
DLLEXPORT alloc_handle_t * AllocInit()
|
|
||||||
{
|
{
|
||||||
alloc_handle_t *newpool;
|
free(memBlock->block);
|
||||||
root = (alloc_root_t *) malloc(sizeof(alloc_root_t));
|
free(memBlock);
|
||||||
if (root == NULL) {
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
if ( (root->first = AllocHdr()) == NULL) {
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
root->current = root->first;
|
|
||||||
newpool = (alloc_handle_t *) root;
|
|
||||||
return(newpool);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
struct Mempool * mempool_create()
|
||||||
** Alloc()
|
|
||||||
**
|
|
||||||
** Use as a direct replacement for malloc(). Allocates
|
|
||||||
** memory from the current pool.
|
|
||||||
*/
|
|
||||||
|
|
||||||
DLLEXPORT char *Alloc(long size)
|
|
||||||
{
|
{
|
||||||
alloc_hdr_t *hdr = root->current;
|
struct Mempool *mempool;
|
||||||
char *ptr;
|
mempool = (struct Mempool *)malloc(sizeof(struct Mempool));
|
||||||
|
if (mempool == NULL) return NULL;
|
||||||
|
mempool->first = createMemBlock();
|
||||||
|
mempool->current = mempool->first;
|
||||||
|
if (mempool->first == NULL) return NULL;
|
||||||
|
return mempool;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mempool_delete(struct Mempool *mempool)
|
||||||
|
{
|
||||||
|
if (mempool == NULL) return;
|
||||||
|
while (mempool->first)
|
||||||
|
{
|
||||||
|
mempool->current = mempool->first->next;
|
||||||
|
deleteMemBlock(mempool->first);
|
||||||
|
mempool->first = mempool->current;
|
||||||
|
}
|
||||||
|
free(mempool);
|
||||||
|
mempool = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mempool_reset(struct Mempool *mempool)
|
||||||
|
{
|
||||||
|
mempool->current = mempool->first;
|
||||||
|
mempool->current->free = mempool->current->block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char * mempool_alloc(struct Mempool *mempool, size_t size)
|
||||||
|
{
|
||||||
|
char* ptr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Align to 4 byte boundary - should be ok for most machines.
|
** Align to 4 byte boundary - should be ok for most machines.
|
||||||
@@ -124,86 +101,37 @@ DLLEXPORT char *Alloc(long size)
|
|||||||
*/
|
*/
|
||||||
size = (size + 3) & 0xfffffffc;
|
size = (size + 3) & 0xfffffffc;
|
||||||
|
|
||||||
ptr = hdr->free;
|
if (!mempool->current) return NULL;
|
||||||
hdr->free += size;
|
ptr = mempool->current->free;
|
||||||
|
mempool->current->free += size;
|
||||||
|
|
||||||
/* Check if the current block is exhausted. */
|
// Check if the current block is exhausted
|
||||||
|
|
||||||
if (hdr->free >= hdr->end)
|
if (mempool->current->free >= mempool->current->end)
|
||||||
{
|
{
|
||||||
/* Is the next block already allocated? */
|
// Is the next block already allocated?
|
||||||
|
|
||||||
if (hdr->next != NULL)
|
if (mempool->current->next)
|
||||||
{
|
{
|
||||||
/* re-use block */
|
// re-use block
|
||||||
hdr->next->free = hdr->next->block;
|
mempool->current->next->free = mempool->current->next->block;
|
||||||
root->current = hdr->next;
|
mempool->current = mempool->current->next;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* extend the pool with a new block */
|
// extend the pool with a new block
|
||||||
if ( (hdr->next = AllocHdr()) == NULL) return(NULL);
|
mempool->current->next = createMemBlock();
|
||||||
root->current = hdr->next;
|
if (!mempool->current->next) return NULL;
|
||||||
|
mempool->current = mempool->current->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set ptr to the first location in the next block */
|
// set ptr to the first location in the next block
|
||||||
ptr = root->current->free;
|
|
||||||
root->current->free += size;
|
ptr = mempool->current->free;
|
||||||
|
mempool->current->free += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return pointer to allocated memory. */
|
// Return pointer to allocated memory
|
||||||
|
|
||||||
return(ptr);
|
return ptr;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** AllocSetPool()
|
|
||||||
**
|
|
||||||
** Change the current pool. Return the old pool.
|
|
||||||
*/
|
|
||||||
|
|
||||||
DLLEXPORT alloc_handle_t * AllocSetPool(alloc_handle_t *newpool)
|
|
||||||
{
|
|
||||||
alloc_handle_t *old = (alloc_handle_t *) root;
|
|
||||||
root = (alloc_root_t *) newpool;
|
|
||||||
return(old);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** AllocReset()
|
|
||||||
**
|
|
||||||
** Reset the current pool for re-use. No memory is freed,
|
|
||||||
** so this is very fast.
|
|
||||||
*/
|
|
||||||
|
|
||||||
DLLEXPORT void AllocReset()
|
|
||||||
{
|
|
||||||
root->current = root->first;
|
|
||||||
root->current->free = root->current->block;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** AllocFreePool()
|
|
||||||
**
|
|
||||||
** Free the memory used by the current pool.
|
|
||||||
** Don't use where AllocReset() could be used.
|
|
||||||
*/
|
|
||||||
|
|
||||||
DLLEXPORT void AllocFreePool()
|
|
||||||
{
|
|
||||||
alloc_hdr_t *tmp,
|
|
||||||
*hdr = root->first;
|
|
||||||
|
|
||||||
while (hdr != NULL)
|
|
||||||
{
|
|
||||||
tmp = hdr->next;
|
|
||||||
free((char *) hdr->block);
|
|
||||||
free((char *) hdr);
|
|
||||||
hdr = tmp;
|
|
||||||
}
|
|
||||||
free((char *) root);
|
|
||||||
root = NULL;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,41 +3,17 @@
|
|||||||
**
|
**
|
||||||
** Header for mempool.c
|
** Header for mempool.c
|
||||||
**
|
**
|
||||||
** The type alloc_handle_t provides an opaque reference to the
|
** A simple pooled memory allocator
|
||||||
** alloc pool - only the alloc routines know its structure.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MEMPOOL_H
|
#ifndef MEMPOOL_H
|
||||||
#define MEMPOOL_H
|
#define MEMPOOL_H
|
||||||
|
|
||||||
#ifndef DLLEXPORT
|
struct Mempool;
|
||||||
#ifdef DLL
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#define DLLEXPORT extern "C" __declspec(dllexport)
|
|
||||||
#else
|
|
||||||
#define DLLEXPORT __declspec(dllexport) __stdcall
|
|
||||||
#endif
|
|
||||||
#elif defined(CYGWIN)
|
|
||||||
#define DLLEXPORT __stdcall
|
|
||||||
#else
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#define DLLEXPORT
|
|
||||||
#else
|
|
||||||
#define DLLEXPORT
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
struct Mempool * mempool_create();
|
||||||
typedef struct
|
void mempool_delete(struct Mempool *mempool);
|
||||||
{
|
void mempool_reset(struct Mempool *mempool);
|
||||||
long dummy;
|
char * mempool_alloc(struct Mempool *mempool, size_t size);
|
||||||
} alloc_handle_t;
|
|
||||||
|
|
||||||
alloc_handle_t *AllocInit(void);
|
|
||||||
char *Alloc(long);
|
|
||||||
alloc_handle_t *AllocSetPool(alloc_handle_t *);
|
|
||||||
void AllocReset(void);
|
|
||||||
void AllocFreePool(void);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -29,9 +29,9 @@ AUTHOR: L. Rossman
|
|||||||
closequal() -- called from ENcloseQ() in EPANET.C
|
closequal() -- called from ENcloseQ() in EPANET.C
|
||||||
|
|
||||||
Calls are made to:
|
Calls are made to:
|
||||||
AllocInit()
|
mempool_create()
|
||||||
Alloc()
|
mempool_alloc()
|
||||||
AllocFree()
|
mempool_delete()
|
||||||
in MEMPOOL.C to utilize a memory pool to prevent excessive malloc'ing
|
in MEMPOOL.C to utilize a memory pool to prevent excessive malloc'ing
|
||||||
when constantly creating and destroying pipe sub-segments during
|
when constantly creating and destroying pipe sub-segments during
|
||||||
the water quality transport calculations.
|
the water quality transport calculations.
|
||||||
@@ -89,7 +89,7 @@ int openqual(EN_Project *pr)
|
|||||||
|
|
||||||
/* Allocate memory pool for WQ segments */
|
/* Allocate memory pool for WQ segments */
|
||||||
qu->OutOfMemory = FALSE;
|
qu->OutOfMemory = FALSE;
|
||||||
qu->SegPool = AllocInit();
|
qu->SegPool = mempool_create();
|
||||||
if (qu->SegPool == NULL) {
|
if (qu->SegPool == NULL) {
|
||||||
errcode = 101;
|
errcode = 101;
|
||||||
}
|
}
|
||||||
@@ -193,8 +193,7 @@ void initqual(EN_Project *pr)
|
|||||||
|
|
||||||
/* Reset memory pool */
|
/* Reset memory pool */
|
||||||
qu->FreeSeg = NULL;
|
qu->FreeSeg = NULL;
|
||||||
AllocSetPool(qu->SegPool);
|
mempool_reset(qu->SegPool);
|
||||||
AllocReset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize avg. reaction rates */
|
/* Initialize avg. reaction rates */
|
||||||
@@ -438,8 +437,7 @@ int closequal(EN_Project *pr)
|
|||||||
/* Free memory pool */
|
/* Free memory pool */
|
||||||
if (qu->SegPool)
|
if (qu->SegPool)
|
||||||
{
|
{
|
||||||
AllocSetPool(qu->SegPool);
|
mempool_delete(qu->SegPool);
|
||||||
AllocFreePool();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(qu->FirstSeg);
|
free(qu->FirstSeg);
|
||||||
@@ -573,7 +571,6 @@ void transport(EN_Project *pr, long tstep)
|
|||||||
|
|
||||||
/* Repeat until elapsed time equals hydraulic time step */
|
/* Repeat until elapsed time equals hydraulic time step */
|
||||||
|
|
||||||
AllocSetPool(qu->SegPool);
|
|
||||||
qtime = 0;
|
qtime = 0;
|
||||||
while (!qu->OutOfMemory && qtime < tstep) { /* Qstep is quality time step */
|
while (!qu->OutOfMemory && qtime < tstep) { /* Qstep is quality time step */
|
||||||
dt = MIN(qu->Qstep, tstep - qtime); /* Current time step */
|
dt = MIN(qu->Qstep, tstep - qtime); /* Current time step */
|
||||||
@@ -793,7 +790,7 @@ void addseg(EN_Project *pr, int k, double v, double c)
|
|||||||
seg = qu->FreeSeg;
|
seg = qu->FreeSeg;
|
||||||
qu->FreeSeg = seg->prev;
|
qu->FreeSeg = seg->prev;
|
||||||
} else {
|
} else {
|
||||||
seg = (struct Sseg *)Alloc(sizeof(struct Sseg));
|
seg = (struct Sseg *) mempool_alloc(qu->SegPool, sizeof(struct Sseg));
|
||||||
if (seg == NULL) {
|
if (seg == NULL) {
|
||||||
qu->OutOfMemory = TRUE;
|
qu->OutOfMemory = TRUE;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ AUTHOR: L. Rossman
|
|||||||
|
|
||||||
#include "epanet2.h"
|
#include "epanet2.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "mempool.h"
|
|
||||||
#include "util/errormanager.h"
|
#include "util/errormanager.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -538,6 +537,8 @@ typedef struct s_ActItem /* Action list item */
|
|||||||
} ActItem;
|
} ActItem;
|
||||||
|
|
||||||
|
|
||||||
|
// Forward declaration of the Mempool structure defined in mempool.h
|
||||||
|
struct Mempool;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char
|
char
|
||||||
@@ -578,7 +579,7 @@ typedef struct {
|
|||||||
Qtime; /// Current quality time (sec)
|
Qtime; /// Current quality time (sec)
|
||||||
|
|
||||||
char OutOfMemory; /* Out of memory indicator */
|
char OutOfMemory; /* Out of memory indicator */
|
||||||
alloc_handle_t *SegPool; // Memory pool for water quality segments
|
struct Mempool *SegPool; // Memory pool for water quality segments
|
||||||
|
|
||||||
Pseg FreeSeg; /* Pointer to unused segment */
|
Pseg FreeSeg; /* Pointer to unused segment */
|
||||||
Pseg *FirstSeg, /* First (downstream) segment in each pipe */
|
Pseg *FirstSeg, /* First (downstream) segment in each pipe */
|
||||||
|
|||||||
@@ -16,9 +16,18 @@ enable_testing()
|
|||||||
# Sets for output directory for executables and libraries.
|
# Sets for output directory for executables and libraries.
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
set(CMAKE_CXX_FLAGS "-std=c++11")
|
||||||
|
endif(UNIX)
|
||||||
|
|
||||||
#Prep ourselves for compiling boost
|
#Prep ourselves for compiling boost
|
||||||
find_package(Boost REQUIRED)
|
if(MSVC)
|
||||||
|
set(Boost_DEBUG OFF)
|
||||||
|
set(Boost_DETAILED_FAILURE_MSG OFF)
|
||||||
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
|
endif(MSVC)
|
||||||
|
set(Boost_THREAD_FOUND OFF)
|
||||||
|
find_package(Boost COMPONENTS thread)
|
||||||
include_directories (${Boost_INCLUDE_DIRS})
|
include_directories (${Boost_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
481
tests/data/example_0.inp
Normal file
481
tests/data/example_0.inp
Normal file
@@ -0,0 +1,481 @@
|
|||||||
|
[TITLE]
|
||||||
|
EPANET Example Network 3
|
||||||
|
Example showing how the percent of Lake water in a dual-source
|
||||||
|
system changes over time.
|
||||||
|
|
||||||
|
[JUNCTIONS]
|
||||||
|
;ID Elev Demand Pattern
|
||||||
|
10 147 0 ;
|
||||||
|
15 32 1 3 ;
|
||||||
|
20 129 0 ;
|
||||||
|
35 12.5 1 4 ;
|
||||||
|
40 131.9 0 ;
|
||||||
|
50 116.5 0 ;
|
||||||
|
60 0 0 ;
|
||||||
|
601 0 0 ;
|
||||||
|
61 0 0 ;
|
||||||
|
101 42 189.95 ;
|
||||||
|
103 43 133.2 ;
|
||||||
|
105 28.5 135.37 ;
|
||||||
|
107 22 54.64 ;
|
||||||
|
109 20.3 231.4 ;
|
||||||
|
111 10 141.94 ;
|
||||||
|
113 2 20.01 ;
|
||||||
|
115 14 52.1 ;
|
||||||
|
117 13.6 117.71 ;
|
||||||
|
119 2 176.13 ;
|
||||||
|
120 0 0 ;
|
||||||
|
121 -2 41.63 ;
|
||||||
|
123 11 1 2 ;
|
||||||
|
125 11 45.6 ;
|
||||||
|
127 56 17.66 ;
|
||||||
|
129 51 0 ;
|
||||||
|
131 6 42.75 ;
|
||||||
|
139 31 5.89 ;
|
||||||
|
141 4 9.85 ;
|
||||||
|
143 -4.5 6.2 ;
|
||||||
|
145 1 27.63 ;
|
||||||
|
147 18.5 8.55 ;
|
||||||
|
149 16 27.07 ;
|
||||||
|
151 33.5 144.48 ;
|
||||||
|
153 66.2 44.17 ;
|
||||||
|
157 13.1 51.79 ;
|
||||||
|
159 6 41.32 ;
|
||||||
|
161 4 15.8 ;
|
||||||
|
163 5 9.42 ;
|
||||||
|
164 5 0 ;
|
||||||
|
166 -2 2.6 ;
|
||||||
|
167 -5 14.56 ;
|
||||||
|
169 -5 0 ;
|
||||||
|
171 -4 39.34 ;
|
||||||
|
173 -4 0 ;
|
||||||
|
177 8 58.17 ;
|
||||||
|
179 8 0 ;
|
||||||
|
181 8 0 ;
|
||||||
|
183 11 0 ;
|
||||||
|
184 16 0 ;
|
||||||
|
185 16 25.65 ;
|
||||||
|
187 12.5 0 ;
|
||||||
|
189 4 107.92 ;
|
||||||
|
191 25 81.9 ;
|
||||||
|
193 18 71.31 ;
|
||||||
|
195 15.5 0 ;
|
||||||
|
197 23 17.04 ;
|
||||||
|
199 -2 119.32 ;
|
||||||
|
201 0.1 44.61 ;
|
||||||
|
203 2 1 5 ;
|
||||||
|
204 21 0 ;
|
||||||
|
205 21 65.36 ;
|
||||||
|
206 1 0 ;
|
||||||
|
207 9 69.39 ;
|
||||||
|
208 16 0 ;
|
||||||
|
209 -2 0.87 ;
|
||||||
|
211 7 8.67 ;
|
||||||
|
213 7 13.94 ;
|
||||||
|
215 7 92.19 ;
|
||||||
|
217 6 24.22 ;
|
||||||
|
219 4 41.32 ;
|
||||||
|
225 8 22.8 ;
|
||||||
|
229 10.5 64.18 ;
|
||||||
|
231 5 16.48 ;
|
||||||
|
237 14 15.61 ;
|
||||||
|
239 13 44.61 ;
|
||||||
|
241 13 0 ;
|
||||||
|
243 14 4.34 ;
|
||||||
|
247 18 70.38 ;
|
||||||
|
249 18 0 ;
|
||||||
|
251 30 24.16 ;
|
||||||
|
253 36 54.52 ;
|
||||||
|
255 27 40.39 ;
|
||||||
|
257 17 0 ;
|
||||||
|
259 25 0 ;
|
||||||
|
261 0 0 ;
|
||||||
|
263 0 0 ;
|
||||||
|
265 0 0 ;
|
||||||
|
267 21 0 ;
|
||||||
|
269 0 0 ;
|
||||||
|
271 6 0 ;
|
||||||
|
273 8 0 ;
|
||||||
|
275 10 0 ;
|
||||||
|
|
||||||
|
[RESERVOIRS]
|
||||||
|
;ID Head Pattern
|
||||||
|
River 220.0 ;
|
||||||
|
Lake 167.0 ;
|
||||||
|
|
||||||
|
[TANKS]
|
||||||
|
;ID Elevation InitLevel MinLevel MaxLevel Diameter MinVol VolCurve
|
||||||
|
1 131.9 13.1 .1 32.1 85 0 ;
|
||||||
|
2 116.5 23.5 6.5 40.3 50 0 ;
|
||||||
|
3 129.0 29.0 4.0 35.5 164 0 ;
|
||||||
|
|
||||||
|
[PIPES]
|
||||||
|
;ID Node1 Node2 Length Diameter Roughness MinorLoss Status
|
||||||
|
20 3 20 99 99 199 0 Open ;
|
||||||
|
40 1 40 99 99 199 0 Open ;
|
||||||
|
50 2 50 99 99 199 0 Open ;
|
||||||
|
60 River 60 1231 24 140 0 Open ;
|
||||||
|
101 10 101 14200 18 110 0 Open ;
|
||||||
|
103 101 103 1350 16 130 0 Open ;
|
||||||
|
105 101 105 2540 12 130 0 Open ;
|
||||||
|
107 105 107 1470 12 130 0 Open ;
|
||||||
|
109 103 109 3940 16 130 0 Open ;
|
||||||
|
111 109 111 2000 12 130 0 Open ;
|
||||||
|
112 115 111 1160 12 130 0 Open ;
|
||||||
|
113 111 113 1680 12 130 0 Open ;
|
||||||
|
114 115 113 2000 8 130 0 Open ;
|
||||||
|
115 107 115 1950 8 130 0 Open ;
|
||||||
|
116 113 193 1660 12 130 0 Open ;
|
||||||
|
117 263 105 2725 12 130 0 Open ;
|
||||||
|
119 115 117 2180 12 130 0 Open ;
|
||||||
|
120 119 120 730 12 130 0 Open ;
|
||||||
|
121 120 117 1870 12 130 0 Open ;
|
||||||
|
122 121 120 2050 8 130 0 Open ;
|
||||||
|
123 121 119 2000 30 141 0 Open ;
|
||||||
|
125 123 121 1500 30 141 0 Open ;
|
||||||
|
129 121 125 930 24 130 0 Open ;
|
||||||
|
131 125 127 3240 24 130 0 Open ;
|
||||||
|
133 20 127 785 20 130 0 Open ;
|
||||||
|
135 127 129 900 24 130 0 Open ;
|
||||||
|
137 129 131 6480 16 130 0 Open ;
|
||||||
|
145 129 139 2750 8 130 0 Open ;
|
||||||
|
147 139 141 2050 8 130 0 Open ;
|
||||||
|
149 143 141 1400 8 130 0 Open ;
|
||||||
|
151 15 143 1650 8 130 0 Open ;
|
||||||
|
153 145 141 3510 12 130 0 Open ;
|
||||||
|
155 147 145 2200 12 130 0 Open ;
|
||||||
|
159 147 149 880 12 130 0 Open ;
|
||||||
|
161 149 151 1020 8 130 0 Open ;
|
||||||
|
163 151 153 1170 12 130 0 Open ;
|
||||||
|
169 125 153 4560 8 130 0 Open ;
|
||||||
|
171 119 151 3460 12 130 0 Open ;
|
||||||
|
173 119 157 2080 30 141 0 Open ;
|
||||||
|
175 157 159 2910 30 141 0 Open ;
|
||||||
|
177 159 161 2000 30 141 0 Open ;
|
||||||
|
179 161 163 430 30 141 0 Open ;
|
||||||
|
180 163 164 150 14 130 0 Open ;
|
||||||
|
181 164 166 490 14 130 0 Open ;
|
||||||
|
183 265 169 590 30 141 0 Open ;
|
||||||
|
185 167 169 60 8 130 0 Open ;
|
||||||
|
186 187 204 99.9 8 130 0 Open ;
|
||||||
|
187 169 171 1270 30 141 0 Open ;
|
||||||
|
189 171 173 50 30 141 0 Open ;
|
||||||
|
191 271 171 760 24 130 0 Open ;
|
||||||
|
193 35 181 30 24 130 0 Open ;
|
||||||
|
195 181 177 30 12 130 0 Open ;
|
||||||
|
197 177 179 30 12 130 0 Open ;
|
||||||
|
199 179 183 210 12 130 0 Open ;
|
||||||
|
201 40 179 1190 12 130 0 Open ;
|
||||||
|
202 185 184 99.9 8 130 0 Open ;
|
||||||
|
203 183 185 510 8 130 0 Open ;
|
||||||
|
204 184 205 4530. 12 130 0 Open ;
|
||||||
|
205 204 185 1325. 12 130 0 Open ;
|
||||||
|
207 189 183 1350 12 130 0 Open ;
|
||||||
|
209 189 187 500 8 130 0 Open ;
|
||||||
|
211 169 269 646 12 130 0 Open ;
|
||||||
|
213 191 187 2560 12 130 0 Open ;
|
||||||
|
215 267 189 1230 12 130 0 Open ;
|
||||||
|
217 191 193 520 12 130 0 Open ;
|
||||||
|
219 193 195 360 12 130 0 Open ;
|
||||||
|
221 161 195 2300 8 130 0 Open ;
|
||||||
|
223 197 191 1150 12 130 0 Open ;
|
||||||
|
225 111 197 2790 12 130 0 Open ;
|
||||||
|
229 173 199 4000 24 141 0 Open ;
|
||||||
|
231 199 201 630 24 141 0 Open ;
|
||||||
|
233 201 203 120 24 130 0 Open ;
|
||||||
|
235 199 273 725 12 130 0 Open ;
|
||||||
|
237 205 207 1200 12 130 0 Open ;
|
||||||
|
238 207 206 450 12 130 0 Open ;
|
||||||
|
239 275 207 1430 12 130 0 Open ;
|
||||||
|
240 206 208 510 12 130 0 Open ;
|
||||||
|
241 208 209 885 12 130 0 Open ;
|
||||||
|
243 209 211 1210 16 130 0 Open ;
|
||||||
|
245 211 213 990 16 130 0 Open ;
|
||||||
|
247 213 215 4285 16 130 0 Open ;
|
||||||
|
249 215 217 1660 16 130 0 Open ;
|
||||||
|
251 217 219 2050 14 130 0 Open ;
|
||||||
|
257 217 225 1560 12 130 0 Open ;
|
||||||
|
261 213 229 2200 8 130 0 Open ;
|
||||||
|
263 229 231 1960 12 130 0 Open ;
|
||||||
|
269 211 237 2080 12 130 0 Open ;
|
||||||
|
271 237 229 790 8 130 0 Open ;
|
||||||
|
273 237 239 510 12 130 0 Open ;
|
||||||
|
275 239 241 35 12 130 0 Open ;
|
||||||
|
277 241 243 2200 12 130 0 Open ;
|
||||||
|
281 241 247 445 10 130 0 Open ;
|
||||||
|
283 239 249 430 12 130 0 Open ;
|
||||||
|
285 247 249 10 12 130 0 Open ;
|
||||||
|
287 247 255 1390 10 130 0 Open ;
|
||||||
|
289 50 255 925 10 130 0 Open ;
|
||||||
|
291 255 253 1100 10 130 0 Open ;
|
||||||
|
293 255 251 1100 8 130 0 Open ;
|
||||||
|
295 249 251 1450 12 130 0 Open ;
|
||||||
|
297 120 257 645 8 130 0 Open ;
|
||||||
|
299 257 259 350 8 130 0 Open ;
|
||||||
|
301 259 263 1400 8 130 0 Open ;
|
||||||
|
303 257 261 1400 8 130 0 Open ;
|
||||||
|
305 117 261 645 12 130 0 Open ;
|
||||||
|
307 261 263 350 12 130 0 Open ;
|
||||||
|
309 265 267 1580 8 130 0 Open ;
|
||||||
|
311 193 267 1170 12 130 0 Open ;
|
||||||
|
313 269 189 646 12 130 0 Open ;
|
||||||
|
315 181 271 260 24 130 0 Open ;
|
||||||
|
317 273 275 2230 8 130 0 Open ;
|
||||||
|
319 273 205 645 12 130 0 Open ;
|
||||||
|
321 163 265 1200 30 141 0 Open ;
|
||||||
|
323 201 275 300 12 130 0 Open ;
|
||||||
|
325 269 271 1290 8 130 0 Open ;
|
||||||
|
329 61 123 45500 30 140 0 Open ;
|
||||||
|
330 60 601 1 30 140 0 Closed ;
|
||||||
|
333 601 61 1 30 140 0 Open ;
|
||||||
|
|
||||||
|
[PUMPS]
|
||||||
|
;ID Node1 Node2 Parameters
|
||||||
|
10 Lake 10 HEAD 1 ;
|
||||||
|
335 60 61 HEAD 2 ;
|
||||||
|
|
||||||
|
[VALVES]
|
||||||
|
;ID Node1 Node2 Diameter Type Setting MinorLoss
|
||||||
|
|
||||||
|
[TAGS]
|
||||||
|
|
||||||
|
[DEMANDS]
|
||||||
|
;Junction Demand Pattern Category
|
||||||
|
|
||||||
|
[STATUS]
|
||||||
|
;ID Status/Setting
|
||||||
|
10 Closed
|
||||||
|
|
||||||
|
[PATTERNS]
|
||||||
|
;ID Multipliers
|
||||||
|
;General Default Demand Pattern
|
||||||
|
1 1.34 1.94 1.46 1.44 .76 .92
|
||||||
|
1 .85 1.07 .96 1.1 1.08 1.19
|
||||||
|
1 1.16 1.08 .96 .83 .79 .74
|
||||||
|
1 .64 .64 .85 .96 1.24 1.67
|
||||||
|
;Demand Pattern for Node 123
|
||||||
|
2 0 0 0 0 0 1219
|
||||||
|
2 0 0 0 1866 1836 1818
|
||||||
|
2 1818 1822 1822 1817 1824 1816
|
||||||
|
2 1833 1817 1830 1814 1840 1859
|
||||||
|
;Demand Pattern for Node 15
|
||||||
|
3 620 620 620 620 620 360
|
||||||
|
3 360 0 0 0 0 360
|
||||||
|
3 360 360 360 360 0 0
|
||||||
|
3 0 0 0 0 360 360
|
||||||
|
;Demand Pattern for Node 35
|
||||||
|
4 1637 1706 1719 1719 1791 1819
|
||||||
|
4 1777 1842 1815 1825 1856 1801
|
||||||
|
4 1819 1733 1664 1620 1613 1620
|
||||||
|
4 1616 1647 1627 1627 1671 1668
|
||||||
|
;Demand Pattern for Node 203
|
||||||
|
5 4439 4531 4511 4582 4531 4582
|
||||||
|
5 4572 4613 4643 4643 4592 4613
|
||||||
|
5 4531 4521 4449 4439 4449 4460
|
||||||
|
5 4439 4419 4368 4399 4470 4480
|
||||||
|
|
||||||
|
[CURVES]
|
||||||
|
;ID X-Value Y-Value
|
||||||
|
;PUMP: Pump Curve for Pump 10 (Lake Source)
|
||||||
|
1 0 104.
|
||||||
|
1 2000. 92.
|
||||||
|
1 4000. 63.
|
||||||
|
;PUMP: Pump Curve for Pump 335 (River Source)
|
||||||
|
2 0 200.
|
||||||
|
2 8000. 138.
|
||||||
|
2 14000. 86.
|
||||||
|
|
||||||
|
[CONTROLS]
|
||||||
|
;Lake source operates only part of the day
|
||||||
|
Link 10 OPEN AT TIME 1
|
||||||
|
Link 10 CLOSED AT TIME 15
|
||||||
|
|
||||||
|
;Pump 335 controlled by level in Tank 1
|
||||||
|
;When pump is closed, bypass pipe is opened
|
||||||
|
Link 335 OPEN IF Node 1 BELOW 17.1
|
||||||
|
Link 335 CLOSED IF Node 1 ABOVE 19.1
|
||||||
|
Link 330 CLOSED IF Node 1 BELOW 17.1
|
||||||
|
Link 330 OPEN IF Node 1 ABOVE 19.1
|
||||||
|
|
||||||
|
|
||||||
|
[RULES]
|
||||||
|
|
||||||
|
[ENERGY]
|
||||||
|
Global Efficiency 75
|
||||||
|
Global Price 0.0
|
||||||
|
Demand Charge 0.0
|
||||||
|
|
||||||
|
[EMITTERS]
|
||||||
|
;Junction Coefficient
|
||||||
|
|
||||||
|
[QUALITY]
|
||||||
|
;Node InitQual
|
||||||
|
|
||||||
|
[SOURCES]
|
||||||
|
;Node Type Quality Pattern
|
||||||
|
|
||||||
|
[REACTIONS]
|
||||||
|
;Type Pipe/Tank Coefficient
|
||||||
|
|
||||||
|
|
||||||
|
[REACTIONS]
|
||||||
|
Order Bulk 1
|
||||||
|
Order Tank 1
|
||||||
|
Order Wall 1
|
||||||
|
Global Bulk 0.0
|
||||||
|
Global Wall 0.0
|
||||||
|
Limiting Potential 0.0
|
||||||
|
Roughness Correlation 0.0
|
||||||
|
|
||||||
|
[MIXING]
|
||||||
|
;Tank Model
|
||||||
|
|
||||||
|
[TIMES]
|
||||||
|
Duration 24:00
|
||||||
|
Hydraulic Timestep 1:00
|
||||||
|
Quality Timestep 0:05
|
||||||
|
Pattern Timestep 1:00
|
||||||
|
Pattern Start 0:00
|
||||||
|
Report Timestep 1:00
|
||||||
|
Report Start 0:00
|
||||||
|
Start ClockTime 12 am
|
||||||
|
Statistic None
|
||||||
|
|
||||||
|
[REPORT]
|
||||||
|
Status Yes
|
||||||
|
Summary No
|
||||||
|
Page 0
|
||||||
|
|
||||||
|
[OPTIONS]
|
||||||
|
Units GPM
|
||||||
|
Headloss H-W
|
||||||
|
Specific Gravity 1.0
|
||||||
|
Viscosity 1.0
|
||||||
|
Trials 40
|
||||||
|
Accuracy 0.001
|
||||||
|
CHECKFREQ 2
|
||||||
|
MAXCHECK 10
|
||||||
|
DAMPLIMIT 0
|
||||||
|
Unbalanced Continue 10
|
||||||
|
Pattern 1
|
||||||
|
Demand Multiplier 1.0
|
||||||
|
Emitter Exponent 0.5
|
||||||
|
Quality Trace Lake
|
||||||
|
Diffusivity 1.0
|
||||||
|
Tolerance 0.01
|
||||||
|
|
||||||
|
[COORDINATES]
|
||||||
|
;Node X-Coord Y-Coord
|
||||||
|
10 9.00 27.85
|
||||||
|
15 38.68 23.76
|
||||||
|
20 29.44 26.91
|
||||||
|
35 25.46 10.52
|
||||||
|
40 27.02 9.81
|
||||||
|
50 33.01 3.01
|
||||||
|
60 23.90 29.94
|
||||||
|
601 23.00 29.49
|
||||||
|
61 23.71 29.03
|
||||||
|
101 13.81 22.94
|
||||||
|
103 12.96 21.31
|
||||||
|
105 16.97 21.28
|
||||||
|
107 18.45 20.46
|
||||||
|
109 17.64 18.92
|
||||||
|
111 20.21 17.53
|
||||||
|
113 22.04 16.61
|
||||||
|
115 20.98 19.18
|
||||||
|
117 21.69 21.28
|
||||||
|
119 23.70 22.76
|
||||||
|
120 22.08 23.10
|
||||||
|
121 23.54 25.50
|
||||||
|
123 23.37 27.31
|
||||||
|
125 24.59 25.64
|
||||||
|
127 29.29 26.40
|
||||||
|
129 30.32 26.39
|
||||||
|
131 37.89 29.55
|
||||||
|
139 33.28 24.54
|
||||||
|
141 35.68 23.08
|
||||||
|
143 37.47 21.97
|
||||||
|
145 33.02 19.29
|
||||||
|
147 30.24 20.38
|
||||||
|
149 29.62 20.74
|
||||||
|
151 28.29 21.39
|
||||||
|
153 28.13 22.63
|
||||||
|
157 24.85 20.16
|
||||||
|
159 23.12 17.50
|
||||||
|
161 25.10 15.28
|
||||||
|
163 25.39 14.98
|
||||||
|
164 25.98 15.14
|
||||||
|
166 26.48 15.13
|
||||||
|
167 25.88 12.98
|
||||||
|
169 25.68 12.74
|
||||||
|
171 26.65 11.80
|
||||||
|
173 26.87 11.59
|
||||||
|
177 25.92 10.59
|
||||||
|
179 25.71 10.40
|
||||||
|
181 25.72 10.74
|
||||||
|
183 25.45 10.18
|
||||||
|
184 25.15 9.52
|
||||||
|
185 25.01 9.67
|
||||||
|
187 23.64 11.04
|
||||||
|
189 24.15 11.37
|
||||||
|
191 22.10 14.07
|
||||||
|
193 22.88 14.35
|
||||||
|
195 23.18 14.72
|
||||||
|
197 20.97 15.18
|
||||||
|
199 29.42 8.44
|
||||||
|
201 30.89 8.57
|
||||||
|
203 31.14 8.89
|
||||||
|
204 23.80 10.90
|
||||||
|
205 29.20 6.46
|
||||||
|
206 31.66 6.64
|
||||||
|
207 31.00 6.61
|
||||||
|
208 32.54 6.81
|
||||||
|
209 33.76 6.59
|
||||||
|
211 34.20 5.54
|
||||||
|
213 35.26 6.16
|
||||||
|
215 39.95 8.73
|
||||||
|
217 42.11 8.67
|
||||||
|
219 44.86 9.32
|
||||||
|
225 43.53 7.38
|
||||||
|
229 36.16 3.49
|
||||||
|
231 38.38 2.54
|
||||||
|
237 35.37 3.08
|
||||||
|
239 35.76 2.31
|
||||||
|
241 35.87 2.11
|
||||||
|
243 37.04 0.00
|
||||||
|
247 35.02 2.05
|
||||||
|
249 35.02 1.81
|
||||||
|
251 34.15 1.10
|
||||||
|
253 32.17 1.88
|
||||||
|
255 33.51 2.45
|
||||||
|
257 21.17 23.32
|
||||||
|
259 20.80 23.40
|
||||||
|
261 20.79 21.45
|
||||||
|
263 20.32 21.57
|
||||||
|
265 25.39 13.60
|
||||||
|
267 23.38 12.95
|
||||||
|
269 25.03 12.14
|
||||||
|
271 25.97 11.00
|
||||||
|
273 29.16 7.38
|
||||||
|
275 31.07 8.29
|
||||||
|
River 24.15 31.06
|
||||||
|
Lake 8.00 27.53
|
||||||
|
1 27.46 9.84
|
||||||
|
2 32.99 3.45
|
||||||
|
3 29.41 27.27
|
||||||
|
|
||||||
|
[VERTICES]
|
||||||
|
;Link X-Coord Y-Coord
|
||||||
|
|
||||||
|
[LABELS]
|
||||||
|
;X-Coord Y-Coord Label & Anchor Node
|
||||||
|
8.00 29.42 "LAKE"
|
||||||
|
25.00 31.10 "RIVER"
|
||||||
|
|
||||||
|
[BACKDROP]
|
||||||
|
DIMENSIONS 6.16 -1.55 46.70 32.61
|
||||||
|
UNITS None
|
||||||
|
FILE
|
||||||
|
OFFSET 0.00 0.00
|
||||||
|
|
||||||
|
[END]
|
||||||
178
tests/data/example_1.inp
Normal file
178
tests/data/example_1.inp
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
[TITLE]
|
||||||
|
EPANET Example Network 1
|
||||||
|
A simple example of modeling chlorine decay. Both bulk and
|
||||||
|
wall reactions are included.
|
||||||
|
|
||||||
|
[JUNCTIONS]
|
||||||
|
;ID Elev Demand Pattern
|
||||||
|
10 710 0 ;
|
||||||
|
11 710 150 ;
|
||||||
|
12 700 150 ;
|
||||||
|
13 695 100 ;
|
||||||
|
21 700 150 ;
|
||||||
|
22 695 200 ;
|
||||||
|
23 690 150 ;
|
||||||
|
31 700 100 ;
|
||||||
|
32 710 100 ;
|
||||||
|
|
||||||
|
[RESERVOIRS]
|
||||||
|
;ID Head Pattern
|
||||||
|
9 800 ;
|
||||||
|
|
||||||
|
[TANKS]
|
||||||
|
;ID Elevation InitLevel MinLevel MaxLevel Diameter MinVol VolCurve
|
||||||
|
2 850 120 100 150 50.5 0 ;
|
||||||
|
|
||||||
|
[PIPES]
|
||||||
|
;ID Node1 Node2 Length Diameter Roughness MinorLoss Status
|
||||||
|
10 10 11 10530 18 100 0 Open ;
|
||||||
|
11 11 12 5280 14 100 0 Open ;
|
||||||
|
12 12 13 5280 10 100 0 Open ;
|
||||||
|
21 21 22 5280 10 100 0 Open ;
|
||||||
|
22 22 23 5280 12 100 0 Open ;
|
||||||
|
31 31 32 5280 6 100 0 Open ;
|
||||||
|
110 2 12 200 18 100 0 Open ;
|
||||||
|
111 11 21 5280 10 100 0 Open ;
|
||||||
|
112 12 22 5280 12 100 0 Open ;
|
||||||
|
113 13 23 5280 8 100 0 Open ;
|
||||||
|
121 21 31 5280 8 100 0 Open ;
|
||||||
|
122 22 32 5280 6 100 0 Open ;
|
||||||
|
|
||||||
|
[PUMPS]
|
||||||
|
;ID Node1 Node2 Parameters
|
||||||
|
9 9 10 HEAD 1 ;
|
||||||
|
|
||||||
|
[VALVES]
|
||||||
|
;ID Node1 Node2 Diameter Type Setting MinorLoss
|
||||||
|
|
||||||
|
[TAGS]
|
||||||
|
|
||||||
|
[DEMANDS]
|
||||||
|
;Junction Demand Pattern Category
|
||||||
|
|
||||||
|
[STATUS]
|
||||||
|
;ID Status/Setting
|
||||||
|
|
||||||
|
[PATTERNS]
|
||||||
|
;ID Multipliers
|
||||||
|
;Demand Pattern
|
||||||
|
1 1.0 1.2 1.4 1.6 1.4 1.2
|
||||||
|
1 1.0 0.8 0.6 0.4 0.6 0.8
|
||||||
|
|
||||||
|
[CURVES]
|
||||||
|
;ID X-Value Y-Value
|
||||||
|
;PUMP: Pump Curve for Pump 9
|
||||||
|
1 1500 250
|
||||||
|
|
||||||
|
[CONTROLS]
|
||||||
|
LINK 9 OPEN IF NODE 2 BELOW 110
|
||||||
|
LINK 9 CLOSED IF NODE 2 ABOVE 140
|
||||||
|
|
||||||
|
|
||||||
|
[RULES]
|
||||||
|
|
||||||
|
[ENERGY]
|
||||||
|
Global Efficiency 75
|
||||||
|
Global Price 0.0
|
||||||
|
Demand Charge 0.0
|
||||||
|
|
||||||
|
[EMITTERS]
|
||||||
|
;Junction Coefficient
|
||||||
|
|
||||||
|
[QUALITY]
|
||||||
|
;Node InitQual
|
||||||
|
10 0.5
|
||||||
|
11 0.5
|
||||||
|
12 0.5
|
||||||
|
13 0.5
|
||||||
|
21 0.5
|
||||||
|
22 0.5
|
||||||
|
23 0.5
|
||||||
|
31 0.5
|
||||||
|
32 0.5
|
||||||
|
9 1.0
|
||||||
|
2 1.0
|
||||||
|
|
||||||
|
[SOURCES]
|
||||||
|
;Node Type Quality Pattern
|
||||||
|
|
||||||
|
[REACTIONS]
|
||||||
|
;Type Pipe/Tank Coefficient
|
||||||
|
|
||||||
|
|
||||||
|
[REACTIONS]
|
||||||
|
Order Bulk 1
|
||||||
|
Order Tank 1
|
||||||
|
Order Wall 1
|
||||||
|
Global Bulk -.5
|
||||||
|
Global Wall -1
|
||||||
|
Limiting Potential 0.0
|
||||||
|
Roughness Correlation 0.0
|
||||||
|
|
||||||
|
[MIXING]
|
||||||
|
;Tank Model
|
||||||
|
|
||||||
|
[TIMES]
|
||||||
|
Duration 24:00
|
||||||
|
Hydraulic Timestep 1:00
|
||||||
|
Quality Timestep 0:05
|
||||||
|
Pattern Timestep 2:00
|
||||||
|
Pattern Start 0:00
|
||||||
|
Report Timestep 1:00
|
||||||
|
Report Start 0:00
|
||||||
|
Start ClockTime 12 am
|
||||||
|
Statistic None
|
||||||
|
|
||||||
|
[REPORT]
|
||||||
|
Status Yes
|
||||||
|
Summary No
|
||||||
|
Page 0
|
||||||
|
|
||||||
|
[OPTIONS]
|
||||||
|
Units GPM
|
||||||
|
Headloss H-W
|
||||||
|
Specific Gravity 1.0
|
||||||
|
Viscosity 1.0
|
||||||
|
Trials 40
|
||||||
|
Accuracy 0.001
|
||||||
|
CHECKFREQ 2
|
||||||
|
MAXCHECK 10
|
||||||
|
DAMPLIMIT 0
|
||||||
|
Unbalanced Continue 10
|
||||||
|
Pattern 1
|
||||||
|
Demand Multiplier 1.0
|
||||||
|
Emitter Exponent 0.5
|
||||||
|
Quality Chlorine mg/L
|
||||||
|
Diffusivity 1.0
|
||||||
|
Tolerance 0.01
|
||||||
|
|
||||||
|
[COORDINATES]
|
||||||
|
;Node X-Coord Y-Coord
|
||||||
|
10 20.00 70.00
|
||||||
|
11 30.00 70.00
|
||||||
|
12 50.00 70.00
|
||||||
|
13 70.00 70.00
|
||||||
|
21 30.00 40.00
|
||||||
|
22 50.00 40.00
|
||||||
|
23 70.00 40.00
|
||||||
|
31 30.00 10.00
|
||||||
|
32 50.00 10.00
|
||||||
|
9 10.00 70.00
|
||||||
|
2 50.00 90.00
|
||||||
|
|
||||||
|
[VERTICES]
|
||||||
|
;Link X-Coord Y-Coord
|
||||||
|
|
||||||
|
[LABELS]
|
||||||
|
;X-Coord Y-Coord Label & Anchor Node
|
||||||
|
6.99 73.63 "Source"
|
||||||
|
13.48 68.13 "Pump"
|
||||||
|
43.85 91.21 "Tank"
|
||||||
|
|
||||||
|
[BACKDROP]
|
||||||
|
DIMENSIONS 7.00 6.00 73.00 94.00
|
||||||
|
UNITS None
|
||||||
|
FILE
|
||||||
|
OFFSET 0.00 0.00
|
||||||
|
|
||||||
|
[END]
|
||||||
65
tests/test_reent.cpp
Normal file
65
tests/test_reent.cpp
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* test_reent.cpp
|
||||||
|
*
|
||||||
|
* Created: 8/30/2018
|
||||||
|
* Author: Michael E. Tryby
|
||||||
|
* US EPA - ORD/NRMRL
|
||||||
|
*
|
||||||
|
* Multi-threading / reentrancy test for EPANET Toolkit API.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
|
#include "epanet2.h"
|
||||||
|
|
||||||
|
#define NUM_THREADS 2
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
void epanet_thread(long i)
|
||||||
|
{
|
||||||
|
int errorcode = 0;
|
||||||
|
EN_ProjectHandle ph;
|
||||||
|
|
||||||
|
string prefix = "example_";
|
||||||
|
string suffix = ".inp";
|
||||||
|
string input = prefix + to_string(static_cast<long long>(i)) + suffix;
|
||||||
|
|
||||||
|
suffix = ".rpt";
|
||||||
|
string report = prefix + to_string(static_cast<long long>(i)) + suffix;
|
||||||
|
|
||||||
|
suffix = ".out";
|
||||||
|
string output = prefix + to_string(static_cast<long long>(i)) + suffix;
|
||||||
|
|
||||||
|
printf("Thread #%ld starting EPANET ...\n", i);
|
||||||
|
|
||||||
|
EN_createproject(&ph);
|
||||||
|
errorcode = EN_runproject(ph, input.c_str(), report.c_str(), output.c_str(), NULL);
|
||||||
|
EN_deleteproject(&ph);
|
||||||
|
|
||||||
|
printf("Thread #%ld EPANET done. Status = %d\n", i, errorcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
long i;
|
||||||
|
boost::thread *threads[NUM_THREADS];
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_THREADS; i++) {
|
||||||
|
threads[i] = new boost::thread(epanet_thread, i);
|
||||||
|
printf("Main: creating thread %ld.\n", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_THREADS; i++) {
|
||||||
|
threads[i]->join();
|
||||||
|
printf("Main: joining thread %ld.\n", i);
|
||||||
|
delete threads[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Main: program completed. Exiting.\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
@@ -204,4 +204,60 @@ BOOST_FIXTURE_TEST_CASE(test_progressive_stepping, Fixture)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(test_setdemandpattern, Fixture)
|
||||||
|
{
|
||||||
|
int i, j, pat_index, pat_index_2, numDemands, nnodes;
|
||||||
|
char newpat[] = "new_pattern";
|
||||||
|
|
||||||
|
// get the number of nodes
|
||||||
|
error = EN_getcount(ph, EN_NODECOUNT, &nnodes);
|
||||||
|
BOOST_REQUIRE(error == 0);
|
||||||
|
|
||||||
|
// add a new pattern
|
||||||
|
error = EN_addpattern(ph, newpat);
|
||||||
|
BOOST_REQUIRE(error == 0);
|
||||||
|
|
||||||
|
// get the new patterns index, should be as the number of patterns
|
||||||
|
error = EN_getpatternindex(ph, newpat, &pat_index);
|
||||||
|
BOOST_REQUIRE(error == 0);
|
||||||
|
|
||||||
|
for (i = 1; i <= nnodes; i++) {
|
||||||
|
// get the number of demand categories
|
||||||
|
error = EN_getnumdemands(ph, i, &numDemands);
|
||||||
|
BOOST_REQUIRE(error == 0);
|
||||||
|
|
||||||
|
for (j = 1; j <= numDemands; j++) {
|
||||||
|
// set demand patterns
|
||||||
|
error = EN_setdemandpattern(ph, i, j, pat_index);
|
||||||
|
BOOST_REQUIRE(error == 0);
|
||||||
|
// get demand patterns should be the same with set
|
||||||
|
error = EN_getdemandpattern(ph, i, j, &pat_index_2);
|
||||||
|
BOOST_REQUIRE(error == 0);
|
||||||
|
BOOST_REQUIRE(pat_index == pat_index_2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BOOST_FIXTURE_TEST_CASE(test_addpattern, Fixture)
|
||||||
|
{
|
||||||
|
int pat_index, n_patterns_1, n_patterns_2;
|
||||||
|
char newpat[] = "new_pattern";
|
||||||
|
|
||||||
|
// get the number of current patterns
|
||||||
|
error = EN_getcount(ph, EN_PATCOUNT, &n_patterns_1);
|
||||||
|
BOOST_REQUIRE(error == 0);
|
||||||
|
|
||||||
|
// add a new pattern
|
||||||
|
error = EN_addpattern(ph, newpat);
|
||||||
|
BOOST_REQUIRE(error == 0);
|
||||||
|
|
||||||
|
// get the new patterns count, shoul dbe the old one + 1
|
||||||
|
error = EN_getcount(ph, EN_PATCOUNT, &n_patterns_2);
|
||||||
|
BOOST_REQUIRE(error == 0);
|
||||||
|
BOOST_REQUIRE(n_patterns_1 + 1 == n_patterns_2);
|
||||||
|
|
||||||
|
// gwt the new patterns index, should be as the number of patterns
|
||||||
|
error = EN_getpatternindex(ph, newpat, &pat_index);
|
||||||
|
BOOST_REQUIRE(pat_index == n_patterns_2);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|||||||
@@ -65,8 +65,10 @@ EXPORTS
|
|||||||
ENsetcoord = _ENsetcoord@12
|
ENsetcoord = _ENsetcoord@12
|
||||||
ENgetqualinfo = _ENgetqualinfo@16
|
ENgetqualinfo = _ENgetqualinfo@16
|
||||||
ENsetbasedemand = _ENsetbasedemand@12
|
ENsetbasedemand = _ENsetbasedemand@12
|
||||||
|
ENsetdemandpattern = _ENsetdemandpattern@12
|
||||||
ENgetaveragepatternvalue = _ENgetaveragepatternvalue@8
|
ENgetaveragepatternvalue = _ENgetaveragepatternvalue@8
|
||||||
ENgetheadcurveindex = _ENgetheadcurveindex@8
|
ENgetheadcurveindex = _ENgetheadcurveindex@8
|
||||||
|
ENsetheadcurveindex = _ENsetheadcurveindex@8
|
||||||
ENgetpumptype = _ENgetpumptype@8
|
ENgetpumptype = _ENgetpumptype@8
|
||||||
ENgetcurveindex = _ENgetcurveindex@8
|
ENgetcurveindex = _ENgetcurveindex@8
|
||||||
ENgetcurveid = _ENgetcurveid@8
|
ENgetcurveid = _ENgetcurveid@8
|
||||||
@@ -96,4 +98,4 @@ EXPORTS
|
|||||||
ENgetdemandmodel = _ENgetdemandmodel@16
|
ENgetdemandmodel = _ENgetdemandmodel@16
|
||||||
ENsetdemandmodel = _ENsetdemandmodel@16
|
ENsetdemandmodel = _ENsetdemandmodel@16
|
||||||
ENgetcurvetype = _ENgetcurvetype@8
|
ENgetcurvetype = _ENgetcurvetype@8
|
||||||
|
ENinit = _ENinit@16
|
||||||
Reference in New Issue
Block a user