Merge branch 'dev' into issue-172
This commit is contained in:
@@ -9,6 +9,7 @@ env:
|
||||
before_install:
|
||||
- sudo apt-get -qq update
|
||||
- sudo apt-get install -y libboost-test-dev
|
||||
- sudo apt-get install -y libboost-thread-dev
|
||||
- sudo apt-get install -y swig
|
||||
|
||||
#install:
|
||||
@@ -24,7 +25,7 @@ script:
|
||||
- cd tests
|
||||
- ctest
|
||||
# run regression tests
|
||||
- cd $EPANET_HOME
|
||||
- pip install -r tools/requirements.txt
|
||||
- tools/before-test.sh $TEST_HOME $EPANET_HOME/$BUILD_HOME/bin $TRAVIS_COMMIT
|
||||
- tools/run-nrtest.sh $TEST_HOME $TRAVIS_COMMIT
|
||||
#- cd $EPANET_HOME
|
||||
#- pip install -r tools/requirements.txt
|
||||
#- tools/before-test.sh $TEST_HOME $EPANET_HOME/$BUILD_HOME/bin $TRAVIS_COMMIT
|
||||
#- tools/run-nrtest.sh $TEST_HOME $TRAVIS_COMMIT
|
||||
|
||||
@@ -75,12 +75,12 @@ source_group("Library" FILES ${EPANET_LIB_ALL})
|
||||
|
||||
|
||||
# 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)
|
||||
|
||||
|
||||
# create export lib so we can link against dll using Visual Studio
|
||||
add_definitions(-D WITH_GENX)
|
||||
add_definitions(-DWITH_GENX)
|
||||
include(GenerateExportHeader)
|
||||
GENERATE_EXPORT_HEADER(epanet
|
||||
BASE_NAME epanet
|
||||
|
||||
@@ -2,8 +2,8 @@ EPANET {#epanet-readme}
|
||||
======
|
||||
|
||||
## Build Status
|
||||
[](https://ci.appveyor.com/project/OpenWaterAnalytics/epanet)
|
||||
[](https://travis-ci.org/OpenWaterAnalytics/EPANET)
|
||||
[](https://ci.appveyor.com/project/OpenWaterAnalytics/epanet/branch/dev)
|
||||
[](https://travis-ci.org/OpenWaterAnalytics/EPANET)
|
||||
|
||||
## 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).
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
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:
|
||||
$$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 |
|
||||
@@ -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**).
|
||||
- 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
|
||||
|
||||
|
||||
@@ -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 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 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 ENgetcurveid Lib "epanet2.dll" (ByVal index As Long, ByVal id As String) As Long
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef WITH_GENX
|
||||
#include "epanet_export.h"
|
||||
#include "epanet_export.h"
|
||||
#else
|
||||
// --- define WINDOWS
|
||||
#undef WINDOWS
|
||||
@@ -1171,12 +1171,15 @@ extern "C" {
|
||||
int DLLEXPORT EN_createproject(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);
|
||||
int DLLEXPORT EN_checkError(EN_ProjectHandle ph, char** msg_buffer);
|
||||
|
||||
//int DLLEXPORT EN_epanet(EN_ProjectHandle ph, const char *f1, const char *f2,
|
||||
// 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);
|
||||
|
||||
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_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_getcurveid(EN_ProjectHandle ph, int index, char *id);
|
||||
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 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 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 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})
|
||||
|
||||
add_definitions(-DWITH_GENX)
|
||||
|
||||
# Creates the EPANET command line executable
|
||||
add_definitions(-D WITH_GENX)
|
||||
add_executable(runepanet ${EPANET_CLI_SOURCES})
|
||||
if(NOT WIN32)
|
||||
target_link_libraries(runepanet LINK_PUBLIC epanet m)
|
||||
|
||||
100
src/epanet.c
100
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
|
||||
// in "legacy mode" with the 2.1-style API.
|
||||
EN_Project *_defaultModel;
|
||||
void *_defaultModel;
|
||||
|
||||
|
||||
// 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 errcode = 0;
|
||||
EN_Project *p = NULL;
|
||||
|
||||
ERRCODE(EN_createproject(&_defaultModel));
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -182,6 +185,14 @@ int DLLEXPORT ENepanet(const char *f1, const char *f2, const char *f3, void (*pv
|
||||
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 errcode = 0;
|
||||
ERRCODE(EN_createproject(&_defaultModel));
|
||||
@@ -473,6 +484,10 @@ int DLLEXPORT ENsetbasedemand(int nodeIndex, int demandIdx,
|
||||
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) {
|
||||
return EN_getdemandpattern(_defaultModel, nodeIndex, demandIdx, pattIdx);
|
||||
}
|
||||
@@ -598,8 +613,29 @@ int DLLEXPORT EN_deleteproject(EN_ProjectHandle *ph)
|
||||
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)
|
||||
/*----------------------------------------------------------------
|
||||
** Input:
|
||||
@@ -620,7 +656,7 @@ int DLLEXPORT EN_init(EN_ProjectHandle *ph, char *f2, char *f3,
|
||||
_fpreset();
|
||||
#endif
|
||||
|
||||
EN_Project *pr = (EN_Project*)*ph;
|
||||
EN_Project *pr = (EN_Project*)ph;
|
||||
|
||||
/* Set system flags */
|
||||
pr->Openflag = TRUE;
|
||||
@@ -3100,7 +3136,7 @@ int DLLEXPORT EN_addpattern(EN_ProjectHandle ph, char *id) {
|
||||
|
||||
if (!p->Openflag)
|
||||
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);
|
||||
|
||||
/* 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++)
|
||||
free(Pattern[i].F);
|
||||
free(Pattern);
|
||||
Pattern = tmpPat;
|
||||
net->Pattern = tmpPat;
|
||||
net->Npats = n;
|
||||
par->MaxPats = n;
|
||||
return set_error(p->error_handle, 0);
|
||||
@@ -3640,7 +3676,7 @@ int DLLEXPORT EN_setheadcurveindex(EN_ProjectHandle ph, int index, int curveinde
|
||||
double *Ucf = p->Ucf;
|
||||
int pIdx;
|
||||
Spump *pump;
|
||||
|
||||
|
||||
if (!p->Openflag)
|
||||
return set_error(p->error_handle, 102);
|
||||
if (index < 1 || index > Nlinks || EN_PUMP != Link[index].Type) {
|
||||
@@ -4474,7 +4510,7 @@ int DLLEXPORT EN_getbasedemand(EN_ProjectHandle ph, int nodeIndex, int demandIdx
|
||||
if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes)
|
||||
return set_error(p->error_handle, 203);
|
||||
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++;
|
||||
}
|
||||
if (n != demandIdx) {
|
||||
@@ -4507,7 +4543,7 @@ int DLLEXPORT EN_setbasedemand(EN_ProjectHandle ph, int nodeIndex, int demandIdx
|
||||
if (nodeIndex <= 0 || nodeIndex > Nnodes)
|
||||
return set_error(pr->error_handle, 203);
|
||||
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++;
|
||||
if (n != demandIdx)
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
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);
|
||||
if (nodeIndex <= 0 || nodeIndex > Nnodes)
|
||||
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++;
|
||||
if (n != demandIdx)
|
||||
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->N1 = N1;
|
||||
link->N2 = N2;
|
||||
link->Stat = OPEN;
|
||||
|
||||
if (linkType == EN_PUMP) {
|
||||
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->Km = 0.0; // Loss coeff
|
||||
link->Len = 0.0;
|
||||
link->Stat = ACTIVE;
|
||||
}
|
||||
// link->Len = 0.0;
|
||||
// link->Kc = 0.01;
|
||||
// link->Km = 0;
|
||||
link->Kb = 0;
|
||||
link->Kw = 0;
|
||||
link->R = 0;
|
||||
link->Rc = 0;
|
||||
link->Rpt = 0;
|
||||
|
||||
if (linkType == EN_CVPIPE) {
|
||||
link->Stat = OPEN;
|
||||
}
|
||||
else {
|
||||
link->Stat = CLOSED;
|
||||
}
|
||||
|
||||
ENHashTableInsert(net->LinkHashTable, link->ID, n);
|
||||
return set_error(p->error_handle, 0);
|
||||
}
|
||||
|
||||
240
src/mempool.c
240
src/mempool.c
@@ -1,17 +1,9 @@
|
||||
/* 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.),
|
||||
** 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.
|
||||
** Based on code by Steve Hill in Graphics Gems III,
|
||||
** David Kirk (ed.), Academic Press, Boston, MA, 1992
|
||||
**
|
||||
*/
|
||||
|
||||
@@ -28,95 +20,80 @@
|
||||
|
||||
#define ALLOC_BLOCK_SIZE 64000 /*(62*1024)*/
|
||||
|
||||
/*
|
||||
** alloc_hdr_t - Header for each block of memory.
|
||||
*/
|
||||
|
||||
typedef struct alloc_hdr_s
|
||||
struct MemBlock
|
||||
{
|
||||
struct alloc_hdr_s *next; /* Next Block */
|
||||
char *block, /* Start of block */
|
||||
*free, /* Next free in block */
|
||||
*end; /* block + block size */
|
||||
} alloc_hdr_t;
|
||||
struct MemBlock *next; // Next block
|
||||
char *block, // Start of block
|
||||
*free, // Next free position in block
|
||||
*end; // block + block size
|
||||
};
|
||||
|
||||
/*
|
||||
** alloc_root_t - Header for the whole pool.
|
||||
*/
|
||||
|
||||
typedef struct alloc_root_s
|
||||
struct Mempool
|
||||
{
|
||||
alloc_hdr_t *first, /* First header in pool */
|
||||
*current; /* Current header */
|
||||
} alloc_root_t;
|
||||
struct MemBlock *first;
|
||||
struct MemBlock *current;
|
||||
};
|
||||
|
||||
/*
|
||||
** 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()
|
||||
static struct MemBlock* createMemBlock()
|
||||
{
|
||||
alloc_hdr_t *hdr;
|
||||
char *block;
|
||||
|
||||
block = (char *) malloc(ALLOC_BLOCK_SIZE);
|
||||
hdr = (alloc_hdr_t *) malloc(sizeof(alloc_hdr_t));
|
||||
|
||||
if (hdr == NULL || block == NULL) return(NULL);
|
||||
hdr->block = block;
|
||||
hdr->free = block;
|
||||
hdr->next = NULL;
|
||||
hdr->end = block + ALLOC_BLOCK_SIZE;
|
||||
|
||||
return(hdr);
|
||||
struct MemBlock* memBlock = malloc(sizeof(struct MemBlock));
|
||||
if (memBlock)
|
||||
{
|
||||
memBlock->block = malloc(ALLOC_BLOCK_SIZE * sizeof(char));
|
||||
if (memBlock->block == NULL)
|
||||
{
|
||||
free(memBlock);
|
||||
return NULL;
|
||||
}
|
||||
memBlock->free = memBlock->block;
|
||||
memBlock->next = NULL;
|
||||
memBlock->end = memBlock->block + ALLOC_BLOCK_SIZE;
|
||||
}
|
||||
return memBlock;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** AllocInit()
|
||||
**
|
||||
** Create a new memory pool with one block.
|
||||
** Returns pointer to the new pool.
|
||||
*/
|
||||
|
||||
DLLEXPORT alloc_handle_t * AllocInit()
|
||||
static void deleteMemBlock(struct MemBlock* memBlock)
|
||||
{
|
||||
alloc_handle_t *newpool;
|
||||
root = (alloc_root_t *) malloc(sizeof(alloc_root_t));
|
||||
if (root == NULL) {
|
||||
return(NULL);
|
||||
}
|
||||
if ( (root->first = AllocHdr()) == NULL) {
|
||||
return(NULL);
|
||||
}
|
||||
root->current = root->first;
|
||||
newpool = (alloc_handle_t *) root;
|
||||
return(newpool);
|
||||
free(memBlock->block);
|
||||
free(memBlock);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Alloc()
|
||||
**
|
||||
** Use as a direct replacement for malloc(). Allocates
|
||||
** memory from the current pool.
|
||||
*/
|
||||
|
||||
DLLEXPORT char *Alloc(long size)
|
||||
struct Mempool * mempool_create()
|
||||
{
|
||||
alloc_hdr_t *hdr = root->current;
|
||||
char *ptr;
|
||||
struct Mempool *mempool;
|
||||
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.
|
||||
@@ -124,86 +101,37 @@ DLLEXPORT char *Alloc(long size)
|
||||
*/
|
||||
size = (size + 3) & 0xfffffffc;
|
||||
|
||||
ptr = hdr->free;
|
||||
hdr->free += size;
|
||||
if (!mempool->current) return NULL;
|
||||
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 */
|
||||
hdr->next->free = hdr->next->block;
|
||||
root->current = hdr->next;
|
||||
// re-use block
|
||||
mempool->current->next->free = mempool->current->next->block;
|
||||
mempool->current = mempool->current->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* extend the pool with a new block */
|
||||
if ( (hdr->next = AllocHdr()) == NULL) return(NULL);
|
||||
root->current = hdr->next;
|
||||
// extend the pool with a new block
|
||||
mempool->current->next = createMemBlock();
|
||||
if (!mempool->current->next) return NULL;
|
||||
mempool->current = mempool->current->next;
|
||||
}
|
||||
|
||||
/* set ptr to the first location in the next block */
|
||||
ptr = root->current->free;
|
||||
root->current->free += size;
|
||||
// set ptr to the first location in the next block
|
||||
|
||||
ptr = mempool->current->free;
|
||||
mempool->current->free += size;
|
||||
}
|
||||
|
||||
/* Return pointer to allocated memory. */
|
||||
// Return pointer to allocated memory
|
||||
|
||||
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;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -3,41 +3,17 @@
|
||||
**
|
||||
** Header for mempool.c
|
||||
**
|
||||
** The type alloc_handle_t provides an opaque reference to the
|
||||
** alloc pool - only the alloc routines know its structure.
|
||||
** A simple pooled memory allocator
|
||||
*/
|
||||
|
||||
#ifndef MEMPOOL_H
|
||||
#define MEMPOOL_H
|
||||
|
||||
#ifndef DLLEXPORT
|
||||
#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;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
long dummy;
|
||||
} alloc_handle_t;
|
||||
|
||||
alloc_handle_t *AllocInit(void);
|
||||
char *Alloc(long);
|
||||
alloc_handle_t *AllocSetPool(alloc_handle_t *);
|
||||
void AllocReset(void);
|
||||
void AllocFreePool(void);
|
||||
struct Mempool * mempool_create();
|
||||
void mempool_delete(struct Mempool *mempool);
|
||||
void mempool_reset(struct Mempool *mempool);
|
||||
char * mempool_alloc(struct Mempool *mempool, size_t size);
|
||||
|
||||
#endif
|
||||
@@ -29,9 +29,9 @@ AUTHOR: L. Rossman
|
||||
closequal() -- called from ENcloseQ() in EPANET.C
|
||||
|
||||
Calls are made to:
|
||||
AllocInit()
|
||||
Alloc()
|
||||
AllocFree()
|
||||
mempool_create()
|
||||
mempool_alloc()
|
||||
mempool_delete()
|
||||
in MEMPOOL.C to utilize a memory pool to prevent excessive malloc'ing
|
||||
when constantly creating and destroying pipe sub-segments during
|
||||
the water quality transport calculations.
|
||||
@@ -89,7 +89,7 @@ int openqual(EN_Project *pr)
|
||||
|
||||
/* Allocate memory pool for WQ segments */
|
||||
qu->OutOfMemory = FALSE;
|
||||
qu->SegPool = AllocInit();
|
||||
qu->SegPool = mempool_create();
|
||||
if (qu->SegPool == NULL) {
|
||||
errcode = 101;
|
||||
}
|
||||
@@ -193,8 +193,7 @@ void initqual(EN_Project *pr)
|
||||
|
||||
/* Reset memory pool */
|
||||
qu->FreeSeg = NULL;
|
||||
AllocSetPool(qu->SegPool);
|
||||
AllocReset();
|
||||
mempool_reset(qu->SegPool);
|
||||
}
|
||||
|
||||
/* Initialize avg. reaction rates */
|
||||
@@ -438,8 +437,7 @@ int closequal(EN_Project *pr)
|
||||
/* Free memory pool */
|
||||
if (qu->SegPool)
|
||||
{
|
||||
AllocSetPool(qu->SegPool);
|
||||
AllocFreePool();
|
||||
mempool_delete(qu->SegPool);
|
||||
}
|
||||
|
||||
free(qu->FirstSeg);
|
||||
@@ -573,7 +571,6 @@ void transport(EN_Project *pr, long tstep)
|
||||
|
||||
/* Repeat until elapsed time equals hydraulic time step */
|
||||
|
||||
AllocSetPool(qu->SegPool);
|
||||
qtime = 0;
|
||||
while (!qu->OutOfMemory && qtime < tstep) { /* Qstep is quality 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;
|
||||
qu->FreeSeg = seg->prev;
|
||||
} else {
|
||||
seg = (struct Sseg *)Alloc(sizeof(struct Sseg));
|
||||
seg = (struct Sseg *) mempool_alloc(qu->SegPool, sizeof(struct Sseg));
|
||||
if (seg == NULL) {
|
||||
qu->OutOfMemory = TRUE;
|
||||
return;
|
||||
|
||||
@@ -22,7 +22,6 @@ AUTHOR: L. Rossman
|
||||
|
||||
#include "epanet2.h"
|
||||
#include "hash.h"
|
||||
#include "mempool.h"
|
||||
#include "util/errormanager.h"
|
||||
|
||||
|
||||
@@ -538,6 +537,8 @@ typedef struct s_ActItem /* Action list item */
|
||||
} ActItem;
|
||||
|
||||
|
||||
// Forward declaration of the Mempool structure defined in mempool.h
|
||||
struct Mempool;
|
||||
|
||||
typedef struct {
|
||||
char
|
||||
@@ -578,7 +579,7 @@ typedef struct {
|
||||
Qtime; /// Current quality time (sec)
|
||||
|
||||
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 *FirstSeg, /* First (downstream) segment in each pipe */
|
||||
|
||||
@@ -16,9 +16,18 @@ enable_testing()
|
||||
# Sets for output directory for executables and libraries.
|
||||
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
|
||||
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})
|
||||
|
||||
|
||||
|
||||
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()
|
||||
|
||||
@@ -65,8 +65,10 @@ EXPORTS
|
||||
ENsetcoord = _ENsetcoord@12
|
||||
ENgetqualinfo = _ENgetqualinfo@16
|
||||
ENsetbasedemand = _ENsetbasedemand@12
|
||||
ENsetdemandpattern = _ENsetdemandpattern@12
|
||||
ENgetaveragepatternvalue = _ENgetaveragepatternvalue@8
|
||||
ENgetheadcurveindex = _ENgetheadcurveindex@8
|
||||
ENsetheadcurveindex = _ENsetheadcurveindex@8
|
||||
ENgetpumptype = _ENgetpumptype@8
|
||||
ENgetcurveindex = _ENgetcurveindex@8
|
||||
ENgetcurveid = _ENgetcurveid@8
|
||||
@@ -96,4 +98,4 @@ EXPORTS
|
||||
ENgetdemandmodel = _ENgetdemandmodel@16
|
||||
ENsetdemandmodel = _ENsetdemandmodel@16
|
||||
ENgetcurvetype = _ENgetcurvetype@8
|
||||
|
||||
ENinit = _ENinit@16
|
||||
Reference in New Issue
Block a user