Merge pull request #1 from michaeltryby/Mariosmsk-fix_bug_getdemandname
Mariosmsk fix bug getdemandname
This commit is contained in:
@@ -28,7 +28,7 @@ env:
|
||||
- TEST_HOME=nrtestsuite
|
||||
|
||||
before_install:
|
||||
- sudo apt-get -qq update
|
||||
# - sudo apt-get -qq update
|
||||
- eval "${MATRIX_EVAL}"
|
||||
|
||||
#install:
|
||||
|
||||
@@ -9,7 +9,7 @@ EPANET {#epanet-readme}
|
||||
|
||||
|
||||
## 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).
|
||||
|
||||
## What is on this Repository?
|
||||
The EPANET Library is a pressurized pipe network hydraulic and water quality analysis toolkit written in C. If you are interested in using/extending EPANET for academic, personal, or commercial use, then you've come to the right place.
|
||||
|
||||
@@ -21,16 +21,15 @@ environment:
|
||||
GENERATOR: "Visual Studio 15 2017"
|
||||
GROUP: "SUPPORTED"
|
||||
BOOST_ROOT: "C:/Libraries/boost_1_67_0"
|
||||
|
||||
PLATFORM: "win32"
|
||||
REF_BUILD_ID: "220dev5"
|
||||
REF_BUILD_ID: "538_1"
|
||||
# New build on Visual Studio 15 2017
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
GENERATOR: "Visual Studio 15 2017 Win64"
|
||||
GROUP: "EXPERIMENTAL"
|
||||
BOOST_ROOT: "C:/Libraries/boost_1_67_0"
|
||||
PLATFORM: "win64"
|
||||
REF_BUILD_ID: "381_2"
|
||||
REF_BUILD_ID: "538_2"
|
||||
|
||||
# called before repo cloning
|
||||
init:
|
||||
|
||||
@@ -140,19 +140,29 @@ Public Const EN_CMD = 9
|
||||
Public Const EN_DDA = 0 ' Demand driven analysis
|
||||
Public Const EN_PDA = 1 ' Pressure driven analysis
|
||||
|
||||
Public Const EN_TRIALS = 0 ' Hydraulic options
|
||||
Public Const EN_TRIALS = 0 ' Simulation options
|
||||
Public Const EN_ACCURACY = 1
|
||||
Public Const EN_TOLERANCE = 2
|
||||
Public Const EN_EMITEXPON = 3
|
||||
Public Const EN_DEMANDMULT = 4
|
||||
Public Const EN_HEADERROR = 5
|
||||
Public Const EN_FLOWCHANGE = 6
|
||||
Public Const EN_DEMANDDEFPAT = 7
|
||||
Public Const EN_HEADLOSSFORM = 8
|
||||
Public Const EN_GLOBALEFFIC = 9
|
||||
Public Const EN_GLOBALPRICE = 10
|
||||
Public Const EN_GLOBALPATTERN = 11
|
||||
Public Const EN_DEMANDCHARGE = 12
|
||||
Public Const EN_HEADLOSSFORM = 7
|
||||
Public Const EN_GLOBALEFFIC = 8
|
||||
Public Const EN_GLOBALPRICE = 9
|
||||
Public Const EN_GLOBALPATTERN = 10
|
||||
Public Const EN_DEMANDCHARGE = 11
|
||||
Public Const EN_SP_GRAVITY = 12
|
||||
Public Const EN_SP_VISCOS = 13
|
||||
Public Const EN_UNBALANCED = 14
|
||||
Public Const EN_CHECKFREQ = 15
|
||||
Public Const EN_MAXCHECK = 16
|
||||
Public Const EN_DAMPLIMIT = 17
|
||||
Public Const EN_SP_DIFFUS = 18
|
||||
Public Const EN_BULKORDER = 19
|
||||
Public Const EN_WALLORDER = 20
|
||||
Public Const EN_TANKORDER = 21
|
||||
Public Const EN_CONCENLIMIT = 22
|
||||
|
||||
Public Const EN_LOWLEVEL = 0 ' Control types
|
||||
Public Const EN_HILEVEL = 1
|
||||
|
||||
@@ -343,7 +343,7 @@ extern "C" {
|
||||
EN_API_FLOAT_TYPE x, EN_API_FLOAT_TYPE y);
|
||||
|
||||
int DLLEXPORT ENgetcurve(int index, char* id, int *nPoints,
|
||||
EN_API_FLOAT_TYPE **xValues, EN_API_FLOAT_TYPE **yValues);
|
||||
EN_API_FLOAT_TYPE *xValues, EN_API_FLOAT_TYPE *yValues);
|
||||
|
||||
int DLLEXPORT ENsetcurve(int index, EN_API_FLOAT_TYPE *xValues,
|
||||
EN_API_FLOAT_TYPE *yValues, int nPoints);
|
||||
|
||||
@@ -145,19 +145,29 @@ Public Const EN_CMD = 9
|
||||
Public Const EN_DDA = 0 ' Demand driven analysis
|
||||
Public Const EN_PDA = 1 ' Pressure driven analysis
|
||||
|
||||
Public Const EN_TRIALS = 0 ' Hydraulic options
|
||||
Public Const EN_TRIALS = 0 ' Simulation options
|
||||
Public Const EN_ACCURACY = 1
|
||||
Public Const EN_TOLERANCE = 2
|
||||
Public Const EN_EMITEXPON = 3
|
||||
Public Const EN_DEMANDMULT = 4
|
||||
Public Const EN_HEADERROR = 5
|
||||
Public Const EN_FLOWCHANGE = 6
|
||||
Public Const EN_DEMANDDEFPAT = 7
|
||||
Public Const EN_HEADLOSSFORM = 8
|
||||
Public Const EN_GLOBALEFFIC = 9
|
||||
Public Const EN_GLOBALPRICE = 10
|
||||
Public Const EN_GLOBALPATTERN = 11
|
||||
Public Const EN_DEMANDCHARGE = 12
|
||||
Public Const EN_HEADLOSSFORM = 7
|
||||
Public Const EN_GLOBALEFFIC = 8
|
||||
Public Const EN_GLOBALPRICE = 9
|
||||
Public Const EN_GLOBALPATTERN = 10
|
||||
Public Const EN_DEMANDCHARGE = 11
|
||||
Public Const EN_SP_GRAVITY = 12
|
||||
Public Const EN_SP_VISCOS = 13
|
||||
Public Const EN_UNBALANCED = 14
|
||||
Public Const EN_CHECKFREQ = 15
|
||||
Public Const EN_MAXCHECK = 16
|
||||
Public Const EN_DAMPLIMIT = 17
|
||||
Public Const EN_SP_DIFFUS = 18
|
||||
Public Const EN_BULKORDER = 19
|
||||
Public Const EN_WALLORDER = 20
|
||||
Public Const EN_TANKORDER = 21
|
||||
Public Const EN_CONCENLIMIT = 22
|
||||
|
||||
Public Const EN_LOWLEVEL = 0 ' Control types
|
||||
Public Const EN_HILEVEL = 1
|
||||
|
||||
@@ -1422,7 +1422,7 @@ typedef struct Project *EN_Project;
|
||||
@ref EN_MAXID characters.
|
||||
*/
|
||||
int DLLEXPORT EN_getcurve(EN_Project ph, int index, char* id, int *nPoints,
|
||||
double **xValues, double **yValues);
|
||||
double *xValues, double *yValues);
|
||||
|
||||
/**
|
||||
@brief assigns a set of data points to a curve.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 03/17/2019
|
||||
Last Updated: 04/03/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -282,24 +282,34 @@ typedef enum {
|
||||
|
||||
/// Simulation options
|
||||
/**
|
||||
These options specify hydraulic convergence criteria, choice of head loss formula, and
|
||||
several other parameters applied on a network-wide basis. They are accessed using the
|
||||
These constants identify the hydraulic and water quality simulation options
|
||||
that are applied on a network-wide basis. They are accessed using the
|
||||
@ref EN_getoption and @ref EN_setoption functions.
|
||||
*/
|
||||
typedef enum {
|
||||
EN_TRIALS = 0, //!< Maximum hydraulic trials allowed
|
||||
EN_ACCURACY = 1, //!< Maximum total relative flow change for hydraulic convergence
|
||||
EN_TRIALS = 0, //!< Maximum hydraulic trials allowed for hydraulic convergence
|
||||
EN_ACCURACY = 1, //!< Total normalized flow change for hydraulic convergence
|
||||
EN_TOLERANCE = 2, //!< Water quality tolerance
|
||||
EN_EMITEXPON = 3, //!< Exponent in emitter discharge formula
|
||||
EN_DEMANDMULT = 4, //!< Global demand multiplier
|
||||
EN_HEADERROR = 5, //!< Maximum head loss error for hydraulic convergence
|
||||
EN_FLOWCHANGE = 6, //!< Maximum flow change for hydraulic convergence
|
||||
EN_DEFDEMANDPAT = 7, //!< Index of the default demand time pattern
|
||||
EN_HEADLOSSFORM = 8, //!< Head loss formula (see @ref EN_HeadLossType)
|
||||
EN_GLOBALEFFIC = 9, //!< Global pump efficiency (percent)
|
||||
EN_GLOBALPRICE = 10, //!< Global energy price per KWH
|
||||
EN_GLOBALPATTERN = 11, //!< Index of a global energy price pattern
|
||||
EN_DEMANDCHARGE = 12 //!< Energy charge per max. KW usage
|
||||
EN_HEADLOSSFORM = 7, //!< Head loss formula (see @ref EN_HeadLossType)
|
||||
EN_GLOBALEFFIC = 8, //!< Global pump efficiency (percent)
|
||||
EN_GLOBALPRICE = 9, //!< Global energy price per KWH
|
||||
EN_GLOBALPATTERN = 10, //!< Index of a global energy price pattern
|
||||
EN_DEMANDCHARGE = 11, //!< Energy charge per max. KW usage
|
||||
EN_SP_GRAVITY = 12, //!< Specific gravity
|
||||
EN_SP_VISCOS = 13, //!< Specific viscosity (relative to water at 20 deg C)
|
||||
EN_UNBALANCED = 14, //!< Extra trials allowed if hydraulics don't converge
|
||||
EN_CHECKFREQ = 15, //!< Frequency of hydraulic status checks
|
||||
EN_MAXCHECK = 16, //!< Maximum trials for status checking
|
||||
EN_DAMPLIMIT = 17, //!< Accuracy level where solution damping begins
|
||||
EN_SP_DIFFUS = 18, //!< Specific diffusivity (relative to chlorine at 20 deg C)
|
||||
EN_BULKORDER = 19, //!< Bulk water reaction order for pipes
|
||||
EN_WALLORDER = 20, //!< Wall reaction order for pipes (either 0 or 1)
|
||||
EN_TANKORDER = 21, //!< Bulk water reaction order for tanks
|
||||
EN_CONCENLIMIT = 22 //!< Limiting concentration for growth reactions
|
||||
} EN_Option;
|
||||
|
||||
/// Types of simple controls
|
||||
|
||||
@@ -139,7 +139,7 @@ int EXPORT_PY_API curv_getlength(Handle ph, int index, int *len);
|
||||
int EXPORT_PY_API curv_gettype(Handle ph, int curveIndex, int *outType);
|
||||
int EXPORT_PY_API curv_getvalue(Handle ph, int curveIndex, int pointIndex, double *x, double *y);
|
||||
int EXPORT_PY_API curv_setvalue(Handle ph, int curveIndex, int pointIndex, double x, double y);
|
||||
int EXPORT_PY_API curv_get(Handle ph, int curveIndex, char* id, int *nValues, double **xValues, double **yValues);
|
||||
int EXPORT_PY_API curv_get(Handle ph, int curveIndex, char* id, int *nValues, double *xValues, double *yValues);
|
||||
int EXPORT_PY_API curv_set(Handle ph, int index, double *x, double *y, int len);
|
||||
|
||||
int EXPORT_PY_API scntl_add(Handle ph, int type, int linkIndex, double setting, int nodeIndex, double level, int *index);
|
||||
|
||||
279
src/epanet.c
279
src/epanet.c
@@ -7,16 +7,20 @@
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 03/17/2019
|
||||
Last Updated: 04/03/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
@@ -168,10 +172,7 @@ int DLLEXPORT EN_init(EN_Project p, const char *rptFile, const char *outFile,
|
||||
initunits(p);
|
||||
inittanks(p);
|
||||
convertunits(p);
|
||||
|
||||
// Initialize the default demand pattern
|
||||
p->parser.MaxPats = 0;
|
||||
getpatterns(p);
|
||||
p->Openflag = TRUE;
|
||||
return errcode;
|
||||
}
|
||||
@@ -226,10 +227,6 @@ int DLLEXPORT EN_open(EN_Project p, const char *inpFile, const char *rptFile,
|
||||
p->parser.InFile = NULL;
|
||||
}
|
||||
|
||||
// Free temporary linked lists used for Patterns & Curves
|
||||
freeTmplist(p->parser.Patlist);
|
||||
freeTmplist(p->parser.Curvelist);
|
||||
|
||||
// If using previously saved hydraulics file then open it
|
||||
if (p->outfile.Hydflag == USE) ERRCODE(openhydfile(p));
|
||||
|
||||
@@ -279,7 +276,7 @@ int DLLEXPORT EN_getcomment(EN_Project p, int object, int index, char *comment)
|
||||
/*----------------------------------------------------------------
|
||||
** Input: object = a type of object (see EN_ObjectType)
|
||||
** index = the object's index
|
||||
** Output: comment = the object's descriptive comment
|
||||
** Output: comment = the object's descriptive comment
|
||||
** Returns: error code
|
||||
** Purpose: Retrieves an object's descriptive comment
|
||||
**----------------------------------------------------------------
|
||||
@@ -840,7 +837,7 @@ int DLLEXPORT EN_closeQ(EN_Project p)
|
||||
if (!p->Openflag) return 102;
|
||||
closequal(p);
|
||||
p->quality.OpenQflag = FALSE;
|
||||
closeoutfile(p);
|
||||
closeoutfile(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1104,8 +1101,7 @@ int DLLEXPORT EN_getoption(EN_Project p, int option, double *value)
|
||||
v = qual->Ctol * Ucf[QUALITY];
|
||||
break;
|
||||
case EN_EMITEXPON:
|
||||
if (hyd->Qexp > 0.0)
|
||||
v = 1.0 / hyd->Qexp;
|
||||
if (hyd->Qexp > 0.0) v = 1.0 / hyd->Qexp;
|
||||
break;
|
||||
case EN_DEMANDMULT:
|
||||
v = hyd->Dmult;
|
||||
@@ -1116,9 +1112,6 @@ int DLLEXPORT EN_getoption(EN_Project p, int option, double *value)
|
||||
case EN_FLOWCHANGE:
|
||||
v = hyd->FlowChangeLimit * Ucf[FLOW];
|
||||
break;
|
||||
case EN_DEFDEMANDPAT:
|
||||
v = hyd->DefPat;
|
||||
break;
|
||||
case EN_HEADLOSSFORM:
|
||||
v = hyd->Formflag;
|
||||
break;
|
||||
@@ -1134,6 +1127,39 @@ int DLLEXPORT EN_getoption(EN_Project p, int option, double *value)
|
||||
case EN_DEMANDCHARGE:
|
||||
v = hyd->Dcost;
|
||||
break;
|
||||
case EN_SP_GRAVITY:
|
||||
v = hyd->SpGrav;
|
||||
break;
|
||||
case EN_SP_VISCOS:
|
||||
v = hyd->Viscos / VISCOS;
|
||||
break;
|
||||
case EN_UNBALANCED:
|
||||
v = hyd->ExtraIter;
|
||||
break;
|
||||
case EN_CHECKFREQ:
|
||||
v = hyd->CheckFreq;
|
||||
break;
|
||||
case EN_MAXCHECK:
|
||||
v = hyd->MaxCheck;
|
||||
break;
|
||||
case EN_DAMPLIMIT:
|
||||
v = hyd->DampLimit;
|
||||
break;
|
||||
case EN_SP_DIFFUS:
|
||||
v = qual->Diffus / DIFFUS;
|
||||
break;
|
||||
case EN_BULKORDER:
|
||||
v = qual->BulkOrder;
|
||||
break;
|
||||
case EN_WALLORDER:
|
||||
v = qual->WallOrder;
|
||||
break;
|
||||
case EN_TANKORDER:
|
||||
v = qual->TankOrder;
|
||||
break;
|
||||
case EN_CONCENLIMIT:
|
||||
v = qual->Climit * p->Ucf[QUALITY];
|
||||
break;
|
||||
|
||||
default:
|
||||
return 251;
|
||||
@@ -1156,16 +1182,28 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
|
||||
Hydraul *hyd = &p->hydraul;
|
||||
Quality *qual = &p->quality;
|
||||
|
||||
Snode *node;
|
||||
Pdemand demand;
|
||||
const int Njuncs = net->Njuncs;
|
||||
int Njuncs = net->Njuncs;
|
||||
double *Ucf = p->Ucf;
|
||||
int i, j;
|
||||
int tmpPat, pat, error;
|
||||
char tmpId[MAXID + 1];
|
||||
int i, j, pat;
|
||||
double Ke, n, ucf;
|
||||
|
||||
if (!p->Openflag) return 102;
|
||||
|
||||
// The EN_UNBALANCED option can be < 0 indicating that the simulation
|
||||
// should be halted if no convergence is reached in EN_TRIALS. Other
|
||||
// values set the number of additional trials to use with no more
|
||||
// link status changes to achieve convergence.
|
||||
if (option == EN_UNBALANCED)
|
||||
{
|
||||
hyd->ExtraIter = (int)value;
|
||||
if (hyd->ExtraIter < 0) hyd->ExtraIter = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// All other option values must be non-negative
|
||||
if (value < 0.0) return 213;
|
||||
|
||||
// Process the speficied option
|
||||
switch (option)
|
||||
{
|
||||
case EN_TRIALS:
|
||||
@@ -1174,12 +1212,11 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
|
||||
break;
|
||||
|
||||
case EN_ACCURACY:
|
||||
if (value < 1.e-5 || value > 1.e-1) return 213;
|
||||
if (value < 1.e-8 || value > 1.e-1) return 213;
|
||||
hyd->Hacc = value;
|
||||
break;
|
||||
|
||||
case EN_TOLERANCE:
|
||||
if (value < 0.0) return 213;
|
||||
qual->Ctol = value / Ucf[QUALITY];
|
||||
break;
|
||||
|
||||
@@ -1196,59 +1233,33 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
|
||||
break;
|
||||
|
||||
case EN_DEMANDMULT:
|
||||
if (value <= 0.0) return 213;
|
||||
hyd->Dmult = value;
|
||||
break;
|
||||
|
||||
case EN_HEADERROR:
|
||||
if (value < 0.0) return 213;
|
||||
hyd->HeadErrorLimit = value / Ucf[HEAD];
|
||||
break;
|
||||
|
||||
case EN_FLOWCHANGE:
|
||||
if (value < 0.0) return 213;
|
||||
hyd->FlowChangeLimit = value / Ucf[FLOW];
|
||||
break;
|
||||
|
||||
case EN_DEFDEMANDPAT:
|
||||
//check that the pattern exists or is set to zero to delete the default pattern
|
||||
pat = ROUND(value);
|
||||
if (pat < 0 || pat > net->Npats) return 205;
|
||||
tmpPat = hyd->DefPat;
|
||||
//get the new pattern ID
|
||||
if (pat == 0)
|
||||
{
|
||||
strncpy(tmpId, p->parser.DefPatID, MAXID);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = EN_getpatternid(p, pat, tmpId);
|
||||
if (error != 0) return error;
|
||||
}
|
||||
// replace node patterns with default pattern
|
||||
for (i = 1; i <= net->Nnodes; i++)
|
||||
{
|
||||
node = &net->Node[i];
|
||||
for (demand = node->D; demand != NULL; demand = demand->next)
|
||||
{
|
||||
if (demand->Pat == tmpPat)
|
||||
{
|
||||
demand->Pat = pat;
|
||||
demand->Name = xstrcpy(&demand->Name, "", MAXID);
|
||||
}
|
||||
}
|
||||
}
|
||||
strncpy(p->parser.DefPatID, tmpId, MAXID);
|
||||
hyd->DefPat = pat;
|
||||
case EN_HEADLOSSFORM:
|
||||
// Can't change if hydraulic solver is open
|
||||
if (p->hydraul.OpenHflag) return 262;
|
||||
i = ROUND(value);
|
||||
if (i < HW || i > CM) return 213;
|
||||
hyd->Formflag = i;
|
||||
if (hyd->Formflag == HW) hyd->Hexp = 1.852;
|
||||
else hyd->Hexp = 2.0;
|
||||
break;
|
||||
|
||||
case EN_GLOBALEFFIC:
|
||||
if (value <= 0.0 || value > 100.0) return 213;
|
||||
if (value <= 1.0 || value > 100.0) return 213;
|
||||
hyd->Epump = value;
|
||||
break;
|
||||
|
||||
case EN_GLOBALPRICE:
|
||||
if (value < 0.0) return 213;
|
||||
hyd->Ecost = value;
|
||||
break;
|
||||
|
||||
@@ -1259,10 +1270,53 @@ int DLLEXPORT EN_setoption(EN_Project p, int option, double value)
|
||||
break;
|
||||
|
||||
case EN_DEMANDCHARGE:
|
||||
if (value < 0.0) return 213;
|
||||
hyd->Dcost = value;
|
||||
break;
|
||||
|
||||
case EN_SP_GRAVITY:
|
||||
if (value <= 0.0) return 213;
|
||||
Ucf[PRESSURE] *= (value / hyd->SpGrav);
|
||||
hyd->SpGrav = value;
|
||||
break;
|
||||
|
||||
case EN_SP_VISCOS:
|
||||
if (value <= 0.0) return 213;
|
||||
hyd->Viscos = value * VISCOS;
|
||||
break;
|
||||
|
||||
case EN_CHECKFREQ:
|
||||
hyd->CheckFreq = (int)value;
|
||||
break;
|
||||
|
||||
case EN_MAXCHECK:
|
||||
hyd->MaxCheck = (int)value;
|
||||
break;
|
||||
|
||||
case EN_DAMPLIMIT:
|
||||
hyd->DampLimit = value;
|
||||
break;
|
||||
|
||||
case EN_SP_DIFFUS:
|
||||
qual->Diffus = value * DIFFUS;
|
||||
break;
|
||||
|
||||
case EN_BULKORDER:
|
||||
qual->BulkOrder = value;
|
||||
break;
|
||||
|
||||
case EN_WALLORDER:
|
||||
if (value == 0.0 || value == 1.0) qual->WallOrder = value;
|
||||
else return 213;
|
||||
break;
|
||||
|
||||
case EN_TANKORDER:
|
||||
qual->TankOrder = value;
|
||||
break;
|
||||
|
||||
case EN_CONCENLIMIT:
|
||||
qual->Climit = value / p->Ucf[QUALITY];
|
||||
break;
|
||||
|
||||
default:
|
||||
return 251;
|
||||
}
|
||||
@@ -1589,13 +1643,20 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, char *chemName,
|
||||
Quality *qual = &p->quality;
|
||||
|
||||
double *Ucf = p->Ucf;
|
||||
int i;
|
||||
int i, oldQualFlag, traceNodeIndex;
|
||||
double ccf = 1.0;
|
||||
|
||||
if (!p->Openflag) return 102;
|
||||
if (qual->OpenQflag) return 262;
|
||||
if (qualType < EN_NONE || qualType > EN_TRACE) return 251;
|
||||
qual->Qualflag = (char)qualType;
|
||||
if (qualType < NONE || qualType > TRACE) return 251;
|
||||
if (qualType == TRACE)
|
||||
{
|
||||
traceNodeIndex = findnode(net, traceNode);
|
||||
if (traceNodeIndex == 0) return 212;
|
||||
}
|
||||
|
||||
oldQualFlag = qual->Qualflag;
|
||||
qual->Qualflag = qualType;
|
||||
qual->Ctol *= Ucf[QUALITY];
|
||||
if (qual->Qualflag == CHEM) // Chemical analysis
|
||||
{
|
||||
@@ -1623,7 +1684,7 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, char *chemName,
|
||||
|
||||
// When changing from CHEM to AGE or TRACE, nodes initial quality
|
||||
// values must be returned to their original ones
|
||||
if ((qual->Qualflag == AGE || qual->Qualflag == TRACE) & (Ucf[QUALITY] != 1))
|
||||
if ((qual->Qualflag == AGE || qual->Qualflag == TRACE) && oldQualFlag == CHEM)
|
||||
{
|
||||
for (i = 1; i <= p->network.Nnodes; i++)
|
||||
{
|
||||
@@ -1693,7 +1754,7 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType)
|
||||
|
||||
demand = (struct Sdemand *)malloc(sizeof(struct Sdemand));
|
||||
demand->Base = 0.0;
|
||||
demand->Pat = hyd->DefPat; // Use default pattern
|
||||
demand->Pat = 0;
|
||||
demand->Name = NULL;
|
||||
demand->next = NULL;
|
||||
node->D = demand;
|
||||
@@ -2778,7 +2839,7 @@ int DLLEXPORT EN_setdemandname(EN_Project p, int nodeIndex, int demandIndex,
|
||||
|
||||
// Check that demandName is not too long
|
||||
if (strlen(demandName) > MAXID) return 250;
|
||||
|
||||
|
||||
// Locate demand category record and assign demandName to it
|
||||
for (d = p->network.Node[nodeIndex].D;
|
||||
n < demandIndex && d->next != NULL; d = d->next) n++;
|
||||
@@ -3880,7 +3941,6 @@ int DLLEXPORT EN_addpattern(EN_Project p, char *id)
|
||||
{
|
||||
Network *net = &p->network;
|
||||
Parser *parser = &p->parser;
|
||||
Hydraul *hyd = &p->hydraul;
|
||||
|
||||
int i, n, err = 0;
|
||||
Spattern *pat;
|
||||
@@ -3915,9 +3975,6 @@ int DLLEXPORT EN_addpattern(EN_Project p, char *id)
|
||||
// Update the number of patterns
|
||||
net->Npats = n;
|
||||
parser->MaxPats = n;
|
||||
|
||||
// Make new pattern be default demand pattern if name matches
|
||||
if (strcmp(id, parser->DefPatID) == 0) hyd->DefPat = n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3946,14 +4003,6 @@ int DLLEXPORT EN_deletepattern(EN_Project p, int index)
|
||||
// Adjust references by other objects to patterns
|
||||
adjustpatterns(net, index);
|
||||
|
||||
// Modify default demand pattern
|
||||
if (hyd->DefPat == index)
|
||||
{
|
||||
hyd->DefPat = 0;
|
||||
strcpy(parser->DefPatID, "");
|
||||
}
|
||||
else if (hyd->DefPat > index) hyd->DefPat--;
|
||||
|
||||
// Modify global energy price pattern
|
||||
if (hyd->Epat == index) hyd->Epat = 0;
|
||||
else if (hyd->Epat > index) hyd->Epat--;
|
||||
@@ -4179,6 +4228,7 @@ int DLLEXPORT EN_addcurve(EN_Project p, char *id)
|
||||
curve = &net->Curve[n];
|
||||
strcpy(curve->ID, id);
|
||||
curve->Comment = NULL;
|
||||
curve->Capacity = 1;
|
||||
curve->Npts = 1;
|
||||
curve->Type = GENERIC_CURVE;
|
||||
curve->X = (double *)calloc(1, sizeof(double));
|
||||
@@ -4250,20 +4300,11 @@ int DLLEXPORT EN_getcurveindex(EN_Project p, char *id, int *index)
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int i;
|
||||
|
||||
*index = 0;
|
||||
if (!p->Openflag) return 102;
|
||||
for (i = 1; i <= p->network.Ncurves; i++)
|
||||
{
|
||||
if (strcmp(id, p->network.Curve[i].ID) == 0)
|
||||
{
|
||||
*index = i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*index = 0;
|
||||
return 206;
|
||||
*index = findcurve(&p->network, id);
|
||||
if (*index == 0) return 206;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DLLEXPORT EN_getcurveid(EN_Project p, int index, char *id)
|
||||
@@ -4352,8 +4393,8 @@ int DLLEXPORT EN_getcurvevalue(EN_Project p, int curveIndex, int pointIndex,
|
||||
if (!p->Openflag) return 102;
|
||||
if (curveIndex < 1 || curveIndex > p->network.Ncurves) return 206;
|
||||
if (pointIndex < 1 || pointIndex > p->network.Curve[curveIndex].Npts) return 251;
|
||||
*x = (double)p->network.Curve[curveIndex].X[pointIndex - 1];
|
||||
*y = (double)p->network.Curve[curveIndex].Y[pointIndex - 1];
|
||||
*x = p->network.Curve[curveIndex].X[pointIndex - 1];
|
||||
*y = p->network.Curve[curveIndex].Y[pointIndex - 1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4367,23 +4408,48 @@ int DLLEXPORT EN_setcurvevalue(EN_Project p, int curveIndex, int pointIndex,
|
||||
** Output: none
|
||||
** Returns: error code
|
||||
** Purpose: sets the value of a specific point on a data curve
|
||||
** Note: if pointIndex exceeds the curve's length a new point is added.
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
Network *net = &p->network;
|
||||
Scurve *curve;
|
||||
double x1 = -1.e37, x2 = 1.e37;
|
||||
int n = pointIndex - 1;
|
||||
|
||||
// Check for valid input
|
||||
if (!p->Openflag) return 102;
|
||||
if (curveIndex <= 0 || curveIndex > net->Ncurves) return 206;
|
||||
curve = &net->Curve[curveIndex];
|
||||
if (pointIndex <= 0 || pointIndex > curve->Npts) return 251;
|
||||
curve->X[pointIndex - 1] = x;
|
||||
curve->Y[pointIndex - 1] = y;
|
||||
if (pointIndex <= 0) return 251;
|
||||
|
||||
// Check that new point maintains increasing x values
|
||||
if (n - 1 >= 0) x1 = curve->X[n-1];
|
||||
if (n + 1 < curve->Npts) x2 = curve->X[n+1];
|
||||
if (x <= x1 || x >= x2) return 230;
|
||||
|
||||
// Expand curve if need be
|
||||
if (pointIndex > curve->Npts) pointIndex = curve->Npts + 1;
|
||||
if (pointIndex >= curve->Capacity)
|
||||
{
|
||||
if (resizecurve(curve, curve->Capacity + 10) > 0) return 101;
|
||||
}
|
||||
|
||||
// Increase curve's number of points if need be
|
||||
if (pointIndex > curve->Npts)
|
||||
{
|
||||
curve->Npts++;
|
||||
n = curve->Npts - 1;
|
||||
}
|
||||
|
||||
// Insert new point into curve
|
||||
curve->X[n] = x;
|
||||
curve->Y[n] = y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DLLEXPORT EN_getcurve(EN_Project p, int index, char *id, int *nPoints,
|
||||
double **xValues, double **yValues)
|
||||
double *xValues, double *yValues)
|
||||
/*----------------------------------------------------------------
|
||||
** Input: index = data curve index
|
||||
** Output: id = ID name of data curve
|
||||
@@ -4408,8 +4474,8 @@ int DLLEXPORT EN_getcurve(EN_Project p, int index, char *id, int *nPoints,
|
||||
*nPoints = curve->Npts;
|
||||
for (i = 0; i < curve->Npts; i++)
|
||||
{
|
||||
*xValues[i] = curve->X[i];
|
||||
*yValues[i] = curve->Y[i];
|
||||
xValues[i] = curve->X[i];
|
||||
yValues[i] = curve->Y[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -4438,15 +4504,12 @@ int DLLEXPORT EN_setcurve(EN_Project p, int index, double *xValues,
|
||||
// Check that x values are increasing
|
||||
for (j = 1; j < nPoints; j++) if (xValues[j-1] >= xValues[j]) return 230;
|
||||
|
||||
// Re-set number of points & reallocate memory for values
|
||||
// Expand size of curve's data arrays if need be
|
||||
curve = &net->Curve[index];
|
||||
curve->Npts = nPoints;
|
||||
curve->X = (double *)realloc(curve->X, nPoints * sizeof(double));
|
||||
curve->Y = (double *)realloc(curve->Y, nPoints * sizeof(double));
|
||||
if (curve->X == NULL) return 101;
|
||||
if (curve->Y == NULL) return 101;
|
||||
if (resizecurve(curve, nPoints) > 0) return 101;
|
||||
|
||||
// Load values into curve
|
||||
curve->Npts = nPoints;
|
||||
for (j = 0; j < nPoints; j++)
|
||||
{
|
||||
curve->X[j] = xValues[j];
|
||||
|
||||
@@ -10,10 +10,12 @@
|
||||
Last Updated: 03/17/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
@@ -645,7 +647,7 @@ int DLLEXPORT ENsetcurvevalue(int curveIndex, int pointIndex, EN_API_FLOAT_TYPE
|
||||
}
|
||||
|
||||
int DLLEXPORT ENgetcurve(int index, char *id, int *nPoints,
|
||||
EN_API_FLOAT_TYPE **xValues, EN_API_FLOAT_TYPE **yValues)
|
||||
EN_API_FLOAT_TYPE *xValues, EN_API_FLOAT_TYPE *yValues)
|
||||
{
|
||||
int i;
|
||||
Network *net = &_defaultProject->network;
|
||||
@@ -657,8 +659,8 @@ int DLLEXPORT ENgetcurve(int index, char *id, int *nPoints,
|
||||
*nPoints = curve->Npts;
|
||||
for (i = 0; i < curve->Npts; i++)
|
||||
{
|
||||
*xValues[i] = (EN_API_FLOAT_TYPE)curve->X[i];
|
||||
*yValues[i] = (EN_API_FLOAT_TYPE)curve->Y[i];
|
||||
xValues[i] = (EN_API_FLOAT_TYPE)curve->X[i];
|
||||
yValues[i] = (EN_API_FLOAT_TYPE)curve->Y[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
235
src/epanet_py.c
235
src/epanet_py.c
@@ -11,8 +11,13 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "epanet_py.h"
|
||||
@@ -39,7 +44,7 @@ int EXPORT_PY_API proj_create(Handle *ph)
|
||||
if (handle != NULL)
|
||||
{
|
||||
EN_createproject(&handle->project);
|
||||
handle->error = error_new_manager(&error_lookup);
|
||||
handle->error = create_error_manager(&error_lookup);
|
||||
*ph = handle;
|
||||
return 0;
|
||||
}
|
||||
@@ -55,7 +60,7 @@ int EXPORT_PY_API proj_delete(Handle *ph)
|
||||
else
|
||||
{
|
||||
EN_deleteproject(&handle->project);
|
||||
error_dst_manager(handle->error);
|
||||
delete_error_manager(handle->error);
|
||||
}
|
||||
free(handle);
|
||||
*ph = NULL;
|
||||
@@ -67,51 +72,51 @@ int EXPORT_PY_API proj_run(Handle ph, const char *input_path,
|
||||
const char *report_path, const char *output_path)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_runproject(pr->project, input_path, report_path, output_path, NULL));
|
||||
return set_error(pr->error, EN_runproject(pr->project, input_path, report_path, output_path, NULL));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API proj_init(Handle ph, const char *rptFile, const char *outFile,
|
||||
EN_FlowUnits unitsType, EN_HeadLossType headLossType)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_init(pr->project, rptFile, outFile, unitsType, headLossType));
|
||||
return set_error(pr->error, EN_init(pr->project, rptFile, outFile, unitsType, headLossType));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API proj_open(Handle ph, const char *inpFile, const char *rptFile,
|
||||
const char *binOutFile)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_open(pr->project, inpFile, rptFile, binOutFile));
|
||||
return set_error(pr->error, EN_open(pr->project, inpFile, rptFile, binOutFile));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API proj_gettitle(Handle ph, char *line1, char *line2, char *line3)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_gettitle(pr->project, line1, line2, line3));
|
||||
return set_error(pr->error, EN_gettitle(pr->project, line1, line2, line3));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API proj_settitle(Handle ph, const char *line1, const char *line2, const char *line3)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_settitle(pr->project, (char *)line1, (char *)line2, (char *)line3));
|
||||
return set_error(pr->error, EN_settitle(pr->project, (char *)line1, (char *)line2, (char *)line3));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API proj_getcount(Handle ph, EN_CountType code, int *count)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getcount(pr->project, code, count));
|
||||
return set_error(pr->error, EN_getcount(pr->project, code, count));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API proj_savefile(Handle ph, const char *filename)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_saveinpfile(pr->project, filename));
|
||||
return set_error(pr->error, EN_saveinpfile(pr->project, filename));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API proj_close(Handle ph)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_close(pr->project));
|
||||
return set_error(pr->error, EN_close(pr->project));
|
||||
}
|
||||
|
||||
|
||||
@@ -120,55 +125,55 @@ int EXPORT_PY_API proj_close(Handle ph)
|
||||
int EXPORT_PY_API hydr_solve(Handle ph)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_solveH(pr->project));
|
||||
return set_error(pr->error, EN_solveH(pr->project));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API hydr_save(Handle ph)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_saveH(pr->project));
|
||||
return set_error(pr->error, EN_saveH(pr->project));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API hydr_open(Handle ph)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_openH(pr->project));
|
||||
return set_error(pr->error, EN_openH(pr->project));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API hydr_init(Handle ph, EN_InitHydOption saveFlag)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_initH(pr->project, saveFlag));
|
||||
return set_error(pr->error, EN_initH(pr->project, saveFlag));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API hydr_run(Handle ph, long *currentTime)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_runH(pr->project, currentTime));
|
||||
return set_error(pr->error, EN_runH(pr->project, currentTime));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API hydr_next(Handle ph, long *tStep)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_nextH(pr->project, tStep));
|
||||
return set_error(pr->error, EN_nextH(pr->project, tStep));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API hydr_close(Handle ph)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_closeH(pr->project));
|
||||
return set_error(pr->error, EN_closeH(pr->project));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API hydr_savefile(Handle ph, char *filename)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_savehydfile(pr->project, filename));
|
||||
return set_error(pr->error, EN_savehydfile(pr->project, filename));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API hydr_usefile(Handle ph, char *filename)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_usehydfile(pr->project, filename));
|
||||
return set_error(pr->error, EN_usehydfile(pr->project, filename));
|
||||
}
|
||||
|
||||
|
||||
@@ -177,43 +182,43 @@ int EXPORT_PY_API hydr_usefile(Handle ph, char *filename)
|
||||
int EXPORT_PY_API qual_solve(Handle ph)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_solveQ(pr->project));
|
||||
return set_error(pr->error, EN_solveQ(pr->project));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API qual_open(Handle ph)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_openQ(pr->project));
|
||||
return set_error(pr->error, EN_openQ(pr->project));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API qual_init(Handle ph, EN_InitHydOption saveFlag)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_initQ(pr->project, saveFlag));
|
||||
return set_error(pr->error, EN_initQ(pr->project, saveFlag));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API qual_run(Handle ph, long *currentTime)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_runQ(pr->project, currentTime));
|
||||
return set_error(pr->error, EN_runQ(pr->project, currentTime));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API qual_next(Handle ph, long *tStep)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_nextQ(pr->project, tStep));
|
||||
return set_error(pr->error, EN_nextQ(pr->project, tStep));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API qual_step(Handle ph, long *timeLeft)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_stepQ(pr->project, timeLeft));
|
||||
return set_error(pr->error, EN_stepQ(pr->project, timeLeft));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API qual_close(Handle ph)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_closeQ(pr->project));
|
||||
return set_error(pr->error, EN_closeQ(pr->project));
|
||||
}
|
||||
|
||||
|
||||
@@ -222,43 +227,43 @@ int EXPORT_PY_API qual_close(Handle ph)
|
||||
int EXPORT_PY_API rprt_writeline(Handle ph, char *line)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_writeline(pr->project, line));
|
||||
return set_error(pr->error, EN_writeline(pr->project, line));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rprt_writeresults(Handle ph)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_report(pr->project));
|
||||
return set_error(pr->error, EN_report(pr->project));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rprt_clear(Handle ph)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_clearreport(pr->project));
|
||||
return set_error(pr->error, EN_clearreport(pr->project));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rprt_reset(Handle ph)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_resetreport(pr->project));
|
||||
return set_error(pr->error, EN_resetreport(pr->project));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rprt_set(Handle ph, char *reportCommand)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setreport(pr->project, reportCommand));
|
||||
return set_error(pr->error, EN_setreport(pr->project, reportCommand));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rprt_setlevel(Handle ph, EN_StatusReport code)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setstatusreport(pr->project, code));
|
||||
return set_error(pr->error, EN_setstatusreport(pr->project, code));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rprt_anlysstats(Handle ph, EN_AnalysisStatistic code, double* value)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getstatistic(pr->project, code, value));
|
||||
return set_error(pr->error, EN_getstatistic(pr->project, code, value));
|
||||
}
|
||||
|
||||
|
||||
@@ -267,55 +272,55 @@ int EXPORT_PY_API rprt_anlysstats(Handle ph, EN_AnalysisStatistic code, double*
|
||||
int EXPORT_PY_API anlys_getoption(Handle ph, EN_Option code, double *value)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getoption(pr->project, (int)code, value));
|
||||
return set_error(pr->error, EN_getoption(pr->project, (int)code, value));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API anlys_setoption(Handle ph, EN_Option code, double value)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setoption(pr->project, (int)code, value));
|
||||
return set_error(pr->error, EN_setoption(pr->project, (int)code, value));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API anlys_getflowunits(Handle ph, int *code)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getflowunits(pr->project, code));
|
||||
return set_error(pr->error, EN_getflowunits(pr->project, code));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API anlys_setflowunits(Handle ph, EN_FlowUnits code)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setflowunits(pr->project, code));
|
||||
return set_error(pr->error, EN_setflowunits(pr->project, code));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API anlys_gettimeparam(Handle ph, EN_TimeParameter code, long *value)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_gettimeparam(pr->project, code, value));
|
||||
return set_error(pr->error, EN_gettimeparam(pr->project, code, value));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API anlys_settimeparam(Handle ph, EN_TimeParameter code, long value)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_settimeparam(pr->project, code, value));
|
||||
return set_error(pr->error, EN_settimeparam(pr->project, code, value));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API anlys_getqualinfo(Handle ph, int *qualcode, char *chemname, char *chemunits, int *tracenode)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getqualinfo(pr->project, qualcode, chemname, chemunits, tracenode));
|
||||
return set_error(pr->error, EN_getqualinfo(pr->project, qualcode, chemname, chemunits, tracenode));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API anlys_getqualtype(Handle ph, int *qualcode, int *tracenode)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getqualtype(pr->project, qualcode, tracenode));
|
||||
return set_error(pr->error, EN_getqualtype(pr->project, qualcode, tracenode));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API anlys_setqualtype(Handle ph, EN_QualityType qualcode, char *chemname, char *chemunits, char *tracenode)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setqualtype(pr->project, qualcode, chemname, chemunits, tracenode));
|
||||
return set_error(pr->error, EN_setqualtype(pr->project, qualcode, chemname, chemunits, tracenode));
|
||||
}
|
||||
|
||||
|
||||
@@ -324,61 +329,61 @@ int EXPORT_PY_API anlys_setqualtype(Handle ph, EN_QualityType qualcode, char *ch
|
||||
int EXPORT_PY_API node_add(Handle ph, char *id, EN_NodeType nodeType)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_addnode(pr->project, id, nodeType));
|
||||
return set_error(pr->error, EN_addnode(pr->project, id, nodeType));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API node_delete(Handle ph, int index, int actionCode)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_deletenode(pr->project, index, actionCode));
|
||||
return set_error(pr->error, EN_deletenode(pr->project, index, actionCode));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API node_getindex(Handle ph, char *id, int *index)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getnodeindex(pr->project, id, index));
|
||||
return set_error(pr->error, EN_getnodeindex(pr->project, id, index));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API node_getid(Handle ph, int index, char *id)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getnodeid(pr->project, index, id));
|
||||
return set_error(pr->error, EN_getnodeid(pr->project, index, id));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API node_setid(Handle ph, int index, char *newid)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getnodeid(pr->project, index, newid));
|
||||
return set_error(pr->error, EN_getnodeid(pr->project, index, newid));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API node_gettype(Handle ph, int index, int *code)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getnodetype(pr->project, index, code));
|
||||
return set_error(pr->error, EN_getnodetype(pr->project, index, code));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API node_getvalue(Handle ph, int index, EN_NodeProperty code, double *value)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getnodevalue(pr->project, index, (int)code, value));
|
||||
return set_error(pr->error, EN_getnodevalue(pr->project, index, (int)code, value));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API node_setvalue(Handle ph, int index, EN_NodeProperty code, double value)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setnodevalue(pr->project, index, (int)code, value));
|
||||
return set_error(pr->error, EN_setnodevalue(pr->project, index, (int)code, value));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API node_getcoord(Handle ph, int index, double *x, double *y)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getcoord(pr->project, index, x, y));
|
||||
return set_error(pr->error, EN_getcoord(pr->project, index, x, y));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API node_setcoord(Handle ph, int index, double x, double y)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setcoord(pr->project, index, x, y));
|
||||
return set_error(pr->error, EN_setcoord(pr->project, index, x, y));
|
||||
}
|
||||
|
||||
|
||||
@@ -387,55 +392,55 @@ int EXPORT_PY_API node_setcoord(Handle ph, int index, double x, double y)
|
||||
int EXPORT_PY_API dmnd_getmodel(Handle ph, int *type, double *pmin, double *preq, double *pexp)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getdemandmodel(pr->project, type, pmin, preq, pexp));
|
||||
return set_error(pr->error, EN_getdemandmodel(pr->project, type, pmin, preq, pexp));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API dmnd_setmodel(Handle ph, int type, double pmin, double preq, double pexp)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setdemandmodel(pr->project, type, pmin, preq, pexp));
|
||||
return set_error(pr->error, EN_setdemandmodel(pr->project, type, pmin, preq, pexp));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API dmnd_getcount(Handle ph, int nodeIndex, int *numDemands)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getnumdemands(pr->project, nodeIndex, numDemands));
|
||||
return set_error(pr->error, EN_getnumdemands(pr->project, nodeIndex, numDemands));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API dmnd_getbase(Handle ph, int nodeIndex, int demandIndex, double *baseDemand)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getbasedemand(pr->project, nodeIndex, demandIndex, baseDemand));
|
||||
return set_error(pr->error, EN_getbasedemand(pr->project, nodeIndex, demandIndex, baseDemand));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API dmnd_setbase(Handle ph, int nodeIndex, int demandIndex, double baseDemand)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setbasedemand(pr->project, nodeIndex, demandIndex, baseDemand));
|
||||
return set_error(pr->error, EN_setbasedemand(pr->project, nodeIndex, demandIndex, baseDemand));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API dmnd_getpattern(Handle ph, int nodeIndex, int demandIndex, int *patIndex)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getdemandpattern(pr->project, nodeIndex, demandIndex, patIndex));
|
||||
return set_error(pr->error, EN_getdemandpattern(pr->project, nodeIndex, demandIndex, patIndex));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API dmnd_setpattern(Handle ph, int nodeIndex, int demandIndex, int patIndex)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setdemandpattern(pr->project, nodeIndex, demandIndex, patIndex));
|
||||
return set_error(pr->error, EN_setdemandpattern(pr->project, nodeIndex, demandIndex, patIndex));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API dmnd_getname(Handle ph, int nodeIndex, int demandIdx, char *demandName)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getdemandname(pr->project, nodeIndex, demandIdx, demandName));
|
||||
return set_error(pr->error, EN_getdemandname(pr->project, nodeIndex, demandIdx, demandName));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API dmnd_setname(Handle ph, int nodeIndex, int demandIdx, char *demandName)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setdemandname(pr->project, nodeIndex, demandIdx, demandName));
|
||||
return set_error(pr->error, EN_setdemandname(pr->project, nodeIndex, demandIdx, demandName));
|
||||
}
|
||||
|
||||
|
||||
@@ -444,67 +449,67 @@ int EXPORT_PY_API dmnd_setname(Handle ph, int nodeIndex, int demandIdx, char *de
|
||||
int EXPORT_PY_API link_add(Handle ph, char *id, EN_LinkType linkType, char *fromNode, char *toNode)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_addlink(pr->project, id, linkType, fromNode, toNode));
|
||||
return set_error(pr->error, EN_addlink(pr->project, id, linkType, fromNode, toNode));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API link_delete(Handle ph, int index, int actionCode)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_deletelink(pr->project, index, actionCode));
|
||||
return set_error(pr->error, EN_deletelink(pr->project, index, actionCode));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API link_getindex(Handle ph, char *id, int *index)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getlinkindex(pr->project, id, index));
|
||||
return set_error(pr->error, EN_getlinkindex(pr->project, id, index));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API link_getid(Handle ph, int index, char *id)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getlinkid(pr->project, index, id));
|
||||
return set_error(pr->error, EN_getlinkid(pr->project, index, id));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API link_setid(Handle ph, int index, char *newid)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setlinkid(pr->project, index, newid));
|
||||
return set_error(pr->error, EN_setlinkid(pr->project, index, newid));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API link_gettype(Handle ph, int index, int *code)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getlinktype(pr->project, index, code));
|
||||
return set_error(pr->error, EN_getlinktype(pr->project, index, code));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API link_settype(Handle ph, int *index, EN_LinkType type, int actionCode)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setlinktype(pr->project, index, type, actionCode));
|
||||
return set_error(pr->error, EN_setlinktype(pr->project, index, type, actionCode));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API link_getnodes(Handle ph, int index, int *node1, int *node2)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getlinknodes(pr->project, index, node1, node2));
|
||||
return set_error(pr->error, EN_getlinknodes(pr->project, index, node1, node2));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API link_setnodes(Handle ph, int index, int node1, int node2)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setlinknodes(pr->project, index, node1, node2));
|
||||
return set_error(pr->error, EN_setlinknodes(pr->project, index, node1, node2));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API link_getvalue(Handle ph, int index, EN_LinkProperty code, double *value)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getlinkvalue(pr->project, index, code, value));
|
||||
return set_error(pr->error, EN_getlinkvalue(pr->project, index, code, value));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API link_setvalue(Handle ph, int index, int code, double value)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setlinkvalue(pr->project, index, code, value));
|
||||
return set_error(pr->error, EN_setlinkvalue(pr->project, index, code, value));
|
||||
}
|
||||
|
||||
|
||||
@@ -513,19 +518,19 @@ int EXPORT_PY_API link_setvalue(Handle ph, int index, int code, double value)
|
||||
int EXPORT_PY_API pump_gettype(Handle ph, int linkIndex, int *outType)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getpumptype(pr->project, linkIndex, outType));
|
||||
return set_error(pr->error, EN_getpumptype(pr->project, linkIndex, outType));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API pump_getheadcurveindex(Handle ph, int pumpIndex, int *curveIndex)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getheadcurveindex(pr->project, pumpIndex, curveIndex));
|
||||
return set_error(pr->error, EN_getheadcurveindex(pr->project, pumpIndex, curveIndex));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API pump_setheadcurveindex(Handle ph, int pumpIndex, int curveIndex)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setheadcurveindex(pr->project, pumpIndex, curveIndex));
|
||||
return set_error(pr->error, EN_setheadcurveindex(pr->project, pumpIndex, curveIndex));
|
||||
}
|
||||
|
||||
|
||||
@@ -534,49 +539,49 @@ int EXPORT_PY_API pump_setheadcurveindex(Handle ph, int pumpIndex, int curveInde
|
||||
int EXPORT_PY_API ptrn_add(Handle ph, char *id)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_addpattern(pr->project, id));
|
||||
return set_error(pr->error, EN_addpattern(pr->project, id));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API ptrn_getindex(Handle ph, char *id, int *index)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getpatternindex(pr->project, id, index));
|
||||
return set_error(pr->error, EN_getpatternindex(pr->project, id, index));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API ptrn_getid(Handle ph, int index, char *id)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getpatternid(pr->project, index, id));
|
||||
return set_error(pr->error, EN_getpatternid(pr->project, index, id));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API ptrn_getlength(Handle ph, int index, int *len)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getpatternlen(pr->project, index, len));
|
||||
return set_error(pr->error, EN_getpatternlen(pr->project, index, len));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API ptrn_getvalue(Handle ph, int index, int period, double *value)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getpatternvalue(pr->project, index, period, value));
|
||||
return set_error(pr->error, EN_getpatternvalue(pr->project, index, period, value));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API ptrn_setvalue(Handle ph, int index, int period, double value)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setpatternvalue(pr->project, index, period, value));
|
||||
return set_error(pr->error, EN_setpatternvalue(pr->project, index, period, value));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API ptrn_getavgvalue(Handle ph, int index, double *value)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getaveragepatternvalue(pr->project, index, value));
|
||||
return set_error(pr->error, EN_getaveragepatternvalue(pr->project, index, value));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API ptrn_set(Handle ph, int index, double *values, int len)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setpattern(pr->project, index, values, len));
|
||||
return set_error(pr->error, EN_setpattern(pr->project, index, values, len));
|
||||
}
|
||||
|
||||
|
||||
@@ -585,55 +590,55 @@ int EXPORT_PY_API ptrn_set(Handle ph, int index, double *values, int len)
|
||||
int EXPORT_PY_API curv_add(Handle ph, char *id)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_addcurve(pr->project, id));
|
||||
return set_error(pr->error, EN_addcurve(pr->project, id));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API curv_getindex(Handle ph, char *id, int *index)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getcurveindex(pr->project, id, index));
|
||||
return set_error(pr->error, EN_getcurveindex(pr->project, id, index));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API curv_getid(Handle ph, int index, char *id)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getcurveid(pr->project, index, id));
|
||||
return set_error(pr->error, EN_getcurveid(pr->project, index, id));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API curv_getlength(Handle ph, int index, int *len)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getcurvelen(pr->project, index, len));
|
||||
return set_error(pr->error, EN_getcurvelen(pr->project, index, len));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API curv_gettype(Handle ph, int index, int *type)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getcurvetype(pr->project, index, type));
|
||||
return set_error(pr->error, EN_getcurvetype(pr->project, index, type));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API curv_getvalue(Handle ph, int curveIndex, int pointIndex, double *x, double *y)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getcurvevalue(pr->project, curveIndex, pointIndex, x, y));
|
||||
return set_error(pr->error, EN_getcurvevalue(pr->project, curveIndex, pointIndex, x, y));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API curv_setvalue(Handle ph, int curveIndex, int pointIndex, double x, double y)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setcurvevalue(pr->project, curveIndex, pointIndex, x, y));
|
||||
return set_error(pr->error, EN_setcurvevalue(pr->project, curveIndex, pointIndex, x, y));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API curv_get(Handle ph, int curveIndex, char* id, int *nValues, double **xValues, double **yValues)
|
||||
int EXPORT_PY_API curv_get(Handle ph, int curveIndex, char* id, int *nValues, double *xValues, double *yValues)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getcurve(pr->project, curveIndex, id, nValues, xValues, yValues));
|
||||
return set_error(pr->error, EN_getcurve(pr->project, curveIndex, id, nValues, xValues, yValues));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API curv_set(Handle ph, int index, double *x, double *y, int len)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setcurve(pr->project, index, x, y, len));
|
||||
return set_error(pr->error, EN_setcurve(pr->project, index, x, y, len));
|
||||
}
|
||||
|
||||
|
||||
@@ -642,25 +647,25 @@ int EXPORT_PY_API curv_set(Handle ph, int index, double *x, double *y, int len)
|
||||
int EXPORT_PY_API scntl_add(Handle ph, int type, int linkIndex, double setting, int nodeIndex, double level, int *index)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_addcontrol(pr->project, type, linkIndex, setting, nodeIndex, level, index));
|
||||
return set_error(pr->error, EN_addcontrol(pr->project, type, linkIndex, setting, nodeIndex, level, index));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API scntl_delete(Handle ph, int index)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_deletecontrol(pr->project, index));
|
||||
return set_error(pr->error, EN_deletecontrol(pr->project, index));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API scntl_get(Handle ph, int controlIndex, int *controlType, int *linkIndex, double *setting, int *nodeIndex, double *level)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getcontrol(pr->project, controlIndex, controlType, linkIndex, setting, nodeIndex, level));
|
||||
return set_error(pr->error, EN_getcontrol(pr->project, controlIndex, controlType, linkIndex, setting, nodeIndex, level));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API scntl_set(Handle ph, int cindex, int ctype, int lindex, double setting, int nindex, double level)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setcontrol(pr->project, cindex, ctype, lindex, setting, nindex, level));
|
||||
return set_error(pr->error, EN_setcontrol(pr->project, cindex, ctype, lindex, setting, nindex, level));
|
||||
}
|
||||
|
||||
|
||||
@@ -669,85 +674,85 @@ int EXPORT_PY_API scntl_set(Handle ph, int cindex, int ctype, int lindex, double
|
||||
int EXPORT_PY_API rcntl_add(Handle ph, char *rule)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_addrule(pr->project, rule));
|
||||
return set_error(pr->error, EN_addrule(pr->project, rule));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rcntl_delete(Handle ph, int index)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_deleterule(pr->project, index));
|
||||
return set_error(pr->error, EN_deleterule(pr->project, index));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rcntl_get(Handle ph, int index, int *nPremises, int *nThenActions, int *nElseActions, double *priority)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getrule(pr->project, index, nPremises, nThenActions, nElseActions, priority));
|
||||
return set_error(pr->error, EN_getrule(pr->project, index, nPremises, nThenActions, nElseActions, priority));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rcntl_getid(Handle ph, int index, char *id)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getruleID(pr->project, index, id));
|
||||
return set_error(pr->error, EN_getruleID(pr->project, index, id));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rcntl_getpremise(Handle ph, int ruleIndex, int premiseIndex, int *logop, int *object, int *objIndex, int *variable, int *relop, int *status, double *value)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getpremise(pr->project, ruleIndex, premiseIndex, logop, object, objIndex, variable, relop, status, value));
|
||||
return set_error(pr->error, EN_getpremise(pr->project, ruleIndex, premiseIndex, logop, object, objIndex, variable, relop, status, value));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rcntl_setpremise(Handle ph, int ruleIndex, int premiseIndex, int logop, int object, int objIndex, int variable, int relop, int status, double value)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setpremise(pr->project, ruleIndex, premiseIndex, logop, object, objIndex, variable, relop, status, value));
|
||||
return set_error(pr->error, EN_setpremise(pr->project, ruleIndex, premiseIndex, logop, object, objIndex, variable, relop, status, value));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rcntl_setpremiseindex(Handle ph, int ruleIndex, int premiseIndex, int objIndex)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setpremiseindex(pr->project, ruleIndex, premiseIndex, objIndex));
|
||||
return set_error(pr->error, EN_setpremiseindex(pr->project, ruleIndex, premiseIndex, objIndex));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rcntl_setpremisestatus(Handle ph, int ruleIndex, int premiseIndex, int status)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setpremisestatus(pr->project, ruleIndex, premiseIndex, status));
|
||||
return set_error(pr->error, EN_setpremisestatus(pr->project, ruleIndex, premiseIndex, status));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rcntl_setpremisevalue(Handle ph, int ruleIndex, int premiseIndex, double value)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setpremisevalue(pr->project, ruleIndex, premiseIndex, value));
|
||||
return set_error(pr->error, EN_setpremisevalue(pr->project, ruleIndex, premiseIndex, value));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rcntl_getthenaction(Handle ph, int ruleIndex, int actionIndex, int *linkIndex, int *status, double *setting)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getthenaction(pr->project, ruleIndex, actionIndex, linkIndex, status, setting));
|
||||
return set_error(pr->error, EN_getthenaction(pr->project, ruleIndex, actionIndex, linkIndex, status, setting));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rcntl_setthenaction(Handle ph, int ruleIndex, int actionIndex, int linkIndex, int status, double setting)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setthenaction(pr->project, ruleIndex, actionIndex, linkIndex, status, setting));
|
||||
return set_error(pr->error, EN_setthenaction(pr->project, ruleIndex, actionIndex, linkIndex, status, setting));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rcntl_getelseaction(Handle ph, int ruleIndex, int actionIndex, int *linkIndex, int *status, double *setting)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_getelseaction(pr->project, ruleIndex, actionIndex, linkIndex, status, setting));
|
||||
return set_error(pr->error, EN_getelseaction(pr->project, ruleIndex, actionIndex, linkIndex, status, setting));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rcntl_setelseaction(Handle ph, int ruleIndex, int actionIndex, int linkIndex, int status, double setting)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setelseaction(pr->project, ruleIndex, actionIndex, linkIndex, status, setting));
|
||||
return set_error(pr->error, EN_setelseaction(pr->project, ruleIndex, actionIndex, linkIndex, status, setting));
|
||||
}
|
||||
|
||||
int EXPORT_PY_API rcntl_setrulepriority(Handle ph, int index, double priority)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_set(pr->error, EN_setrulepriority(pr->project, index, priority));
|
||||
return set_error(pr->error, EN_setrulepriority(pr->project, index, priority));
|
||||
}
|
||||
|
||||
|
||||
@@ -756,7 +761,7 @@ int EXPORT_PY_API rcntl_setrulepriority(Handle ph, int index, double priority)
|
||||
void EXPORT_PY_API err_clear(Handle ph)
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
error_clear(pr->error);
|
||||
clear_error(pr->error);
|
||||
}
|
||||
|
||||
int EXPORT_PY_API err_check(Handle ph, char** msg_buffer)
|
||||
@@ -767,7 +772,7 @@ int EXPORT_PY_API err_check(Handle ph, char** msg_buffer)
|
||||
//
|
||||
{
|
||||
handle_t *pr = (handle_t *)ph;
|
||||
return error_check(pr->error, msg_buffer);
|
||||
return check_error(pr->error, msg_buffer);
|
||||
}
|
||||
|
||||
int EXPORT_PY_API toolkit_getversion(int *version)
|
||||
|
||||
10
src/funcs.h
10
src/funcs.h
@@ -7,7 +7,7 @@
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 03/17/2019
|
||||
Last Updated: 04/03/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef FUNCS_H
|
||||
@@ -17,8 +17,6 @@
|
||||
|
||||
void initpointers(Project *);
|
||||
int allocdata(Project *);
|
||||
void freeTmplist(STmplist *);
|
||||
void freeFloatlist(SFloatlist *);
|
||||
void freedata(Project *);
|
||||
|
||||
int openfiles(Project *, const char *, const char *,const char *);
|
||||
@@ -36,8 +34,12 @@ int findlink(Network *, char *);
|
||||
int findtank(Network *, int);
|
||||
int findvalve(Network *, int);
|
||||
int findpump(Network *, int);
|
||||
int findpattern(Network *, char *);
|
||||
int findcurve(Network *, char *);
|
||||
|
||||
void adjustpatterns(Network *, int);
|
||||
void adjustcurves(Network *, int);
|
||||
int resizecurve(Scurve *, int);
|
||||
|
||||
int getcomment(Network *, int, int, char *);
|
||||
int setcomment(Network *, int, int, const char *);
|
||||
@@ -65,8 +67,6 @@ void convertunits(Project *);
|
||||
int netsize(Project *);
|
||||
int readdata(Project *);
|
||||
int updatepumpparams(Project *, int);
|
||||
int getpatterns(Project *);
|
||||
int getcurves(Project *);
|
||||
int findmatch(char *, char *[]);
|
||||
int match(const char *, const char *);
|
||||
int gettokens(char *, char **, int, char *);
|
||||
|
||||
18
src/hash.c
18
src/hash.c
@@ -11,11 +11,13 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include "hash.h"
|
||||
|
||||
@@ -84,7 +86,7 @@ int hashtable_update(HashTable *ht, char *key, int new_data)
|
||||
{
|
||||
unsigned int i = gethash(key);
|
||||
DataEntry *entry;
|
||||
|
||||
|
||||
if ( i >= HASHTABLEMAXSIZE ) return NOTFOUND;
|
||||
entry = ht[i];
|
||||
while (entry != NULL)
|
||||
@@ -104,7 +106,7 @@ int hashtable_delete(HashTable *ht, char *key)
|
||||
{
|
||||
unsigned int i = gethash(key);
|
||||
DataEntry *entry, *preventry;
|
||||
|
||||
|
||||
if ( i >= HASHTABLEMAXSIZE ) return NOTFOUND;
|
||||
|
||||
preventry = NULL;
|
||||
@@ -164,7 +166,7 @@ void hashtable_free(HashTable *ht)
|
||||
{
|
||||
DataEntry *entry, *nextentry;
|
||||
int i;
|
||||
|
||||
|
||||
for (i = 0; i < HASHTABLEMAXSIZE; i++)
|
||||
{
|
||||
entry = ht[i];
|
||||
|
||||
@@ -11,13 +11,16 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "types.h"
|
||||
@@ -85,12 +88,12 @@ void resistcoeff(Project *pr, int k)
|
||||
|
||||
double e, d, L;
|
||||
Slink *link = &net->Link[k];
|
||||
|
||||
|
||||
link->Qa = 0.0;
|
||||
switch (link->Type) {
|
||||
|
||||
// ... Link is a pipe. Compute resistance based on headloss formula.
|
||||
// Friction factor for D-W formula gets included during head loss
|
||||
// Friction factor for D-W formula gets included during head loss
|
||||
// calculation.
|
||||
case CVPIPE:
|
||||
case PIPE:
|
||||
@@ -244,14 +247,14 @@ void linkcoeffs(Project *pr)
|
||||
|
||||
// Update linear system coeffs. associated with start node n1
|
||||
// ... node n1 is junction
|
||||
if (n1 <= net->Njuncs)
|
||||
if (n1 <= net->Njuncs)
|
||||
{
|
||||
sm->Aii[sm->Row[n1]] += hyd->P[k]; // Diagonal coeff.
|
||||
sm->F[sm->Row[n1]] += hyd->Y[k]; // RHS coeff.
|
||||
}
|
||||
|
||||
// ... node n1 is a tank/reservoir
|
||||
else sm->F[sm->Row[n2]] += (hyd->P[k] * hyd->NodeHead[n1]);
|
||||
else sm->F[sm->Row[n2]] += (hyd->P[k] * hyd->NodeHead[n1]);
|
||||
|
||||
// Update linear system coeffs. associated with end node n2
|
||||
// ... node n2 is junction
|
||||
@@ -262,7 +265,7 @@ void linkcoeffs(Project *pr)
|
||||
}
|
||||
|
||||
// ... node n2 is a tank/reservoir
|
||||
else sm->F[sm->Row[n1]] += (hyd->P[k] * hyd->NodeHead[n2]);
|
||||
else sm->F[sm->Row[n1]] += (hyd->P[k] * hyd->NodeHead[n2]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,13 +324,13 @@ void valvecoeffs(Project *pr)
|
||||
// Coeffs. for fixed status valves have already been computed
|
||||
if (hyd->LinkSetting[k] == MISSING) continue;
|
||||
|
||||
// Start & end nodes of valve's link
|
||||
// Start & end nodes of valve's link
|
||||
link = &net->Link[k];
|
||||
n1 = link->N1;
|
||||
n2 = link->N2;
|
||||
|
||||
// Call valve-specific function
|
||||
switch (link->Type)
|
||||
switch (link->Type)
|
||||
{
|
||||
case PRV:
|
||||
prvcoeff(pr, k, n1, n2);
|
||||
@@ -482,7 +485,7 @@ void demandcoeffs(Project *pr)
|
||||
double dp, // pressure range over which demand can vary (ft)
|
||||
n, // exponent in head loss v. demand function
|
||||
hloss, // head loss in supplying demand (ft)
|
||||
hgrad; // gradient of demand head loss (ft/cfs)
|
||||
hgrad; // gradient of demand head loss (ft/cfs)
|
||||
|
||||
// Get demand function parameters
|
||||
if (hyd->DemandModel == DDA) return;
|
||||
@@ -659,12 +662,12 @@ void DWpipecoeff(Project *pr, int k)
|
||||
Slink *link = &pr->network.Link[k];
|
||||
|
||||
double q = ABS(hyd->LinkFlow[k]);
|
||||
double r = link->R; // Resistance coeff.
|
||||
double ml = link->Km; // Minor loss coeff.
|
||||
double r = link->R; // Resistance coeff.
|
||||
double ml = link->Km; // Minor loss coeff.
|
||||
double e = link->Kc / link->Diam; // Relative roughness
|
||||
double s = hyd->Viscos * link->Diam; // Viscosity / diameter
|
||||
double hloss, hgrad, f, dfdq, r1;
|
||||
|
||||
|
||||
// Compute head loss and its derivative
|
||||
// ... use Hagen-Poiseuille formula for laminar flow (Re <= 2000)
|
||||
if (q <= A2 * s)
|
||||
@@ -673,7 +676,7 @@ void DWpipecoeff(Project *pr, int k)
|
||||
hloss = hyd->LinkFlow[k] * (r + ml * q);
|
||||
hgrad = r + 2.0 * ml * q;
|
||||
}
|
||||
|
||||
|
||||
// ... otherwise use Darcy-Weisbach formula with friction factor
|
||||
else
|
||||
{
|
||||
@@ -683,7 +686,7 @@ void DWpipecoeff(Project *pr, int k)
|
||||
hloss = r1 * q * hyd->LinkFlow[k];
|
||||
hgrad = (2.0 * r1 * q) + (dfdq * r * q * q);
|
||||
}
|
||||
|
||||
|
||||
// Compute P and Y coefficients
|
||||
hyd->P[k] = 1.0 / hgrad;
|
||||
hyd->Y[k] = hloss / hgrad;
|
||||
@@ -753,7 +756,7 @@ void pumpcoeff(Project *pr, int k)
|
||||
|
||||
int p; // Pump index
|
||||
double h0, // Shutoff head
|
||||
q, // Abs. value of flow
|
||||
q, // Abs. value of flow
|
||||
r, // Flow resistance coeff.
|
||||
n, // Flow exponent coeff.
|
||||
setting, // Pump speed setting
|
||||
@@ -899,7 +902,7 @@ void gpvcoeff(Project *pr, int k)
|
||||
Hydraul *hyd = &pr->hydraul;
|
||||
|
||||
// Treat as a pipe if valve closed
|
||||
if (hyd->LinkStatus[k] == CLOSED) valvecoeff(pr, k);
|
||||
if (hyd->LinkStatus[k] == CLOSED) valvecoeff(pr, k);
|
||||
|
||||
// Otherwise utilize segment of head loss curve
|
||||
// bracketing current flow (curve index is stored
|
||||
@@ -939,7 +942,7 @@ void pbvcoeff(Project *pr, int k)
|
||||
// If valve fixed OPEN or CLOSED then treat as a pipe
|
||||
if (hyd->LinkSetting[k] == MISSING || hyd->LinkSetting[k] == 0.0)
|
||||
{
|
||||
valvecoeff(pr, k);
|
||||
valvecoeff(pr, k);
|
||||
}
|
||||
|
||||
// If valve is active
|
||||
@@ -948,7 +951,7 @@ void pbvcoeff(Project *pr, int k)
|
||||
// Treat as a pipe if minor loss > valve setting
|
||||
if (link->Km * SQR(hyd->LinkFlow[k]) > hyd->LinkSetting[k])
|
||||
{
|
||||
valvecoeff(pr, k);
|
||||
valvecoeff(pr, k);
|
||||
}
|
||||
// Otherwise force headloss across valve to be equal to setting
|
||||
else
|
||||
@@ -983,7 +986,7 @@ void tcvcoeff(Project *pr, int k)
|
||||
}
|
||||
|
||||
// Then apply usual valve formula
|
||||
valvecoeff(pr, k);
|
||||
valvecoeff(pr, k);
|
||||
|
||||
// Restore original loss coeff.
|
||||
link->Km = km;
|
||||
@@ -1017,7 +1020,7 @@ void prvcoeff(Project *pr, int k, int n1, int n2)
|
||||
{
|
||||
|
||||
// Set coeffs. to force head at downstream
|
||||
// node equal to valve setting & force flow
|
||||
// node equal to valve setting & force flow
|
||||
// to equal to flow excess at downstream node.
|
||||
|
||||
hyd->P[k] = 0.0;
|
||||
@@ -1069,7 +1072,7 @@ void psvcoeff(Project *pr, int k, int n1, int n2)
|
||||
if (hyd->LinkStatus[k] == ACTIVE)
|
||||
{
|
||||
// Set coeffs. to force head at upstream
|
||||
// node equal to valve setting & force flow
|
||||
// node equal to valve setting & force flow
|
||||
// equal to flow excess at upstream node.
|
||||
|
||||
hyd->P[k] = 0.0;
|
||||
@@ -1138,7 +1141,7 @@ void fcvcoeff(Project *pr, int k, int n1, int n2)
|
||||
|
||||
else
|
||||
{
|
||||
valvecoeff(pr, k);
|
||||
valvecoeff(pr, k);
|
||||
sm->Aij[sm->Ndx[k]] -= hyd->P[k];
|
||||
sm->Aii[i] += hyd->P[k];
|
||||
sm->Aii[j] += hyd->P[k];
|
||||
@@ -1162,7 +1165,7 @@ void valvecoeff(Project *pr, int k)
|
||||
Slink *link = &pr->network.Link[k];
|
||||
|
||||
double flow, q, y, qa, hgrad;
|
||||
|
||||
|
||||
flow = hyd->LinkFlow[k];
|
||||
|
||||
// Valve is closed. Use a very small matrix coeff.
|
||||
|
||||
227
src/hydraul.c
227
src/hydraul.c
@@ -3,7 +3,7 @@
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Module: hydraul.c
|
||||
Description: implements EPANET's hydraulic engine
|
||||
Description: implements EPANET's hydraulic engine
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
@@ -11,13 +11,16 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "types.h"
|
||||
@@ -48,9 +51,9 @@ void tanklevels(Project *, long);
|
||||
int openhyd(Project *pr)
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
* Input: none
|
||||
* Output: returns error code
|
||||
* Purpose: opens hydraulics solver system
|
||||
* Input: none
|
||||
* Output: returns error code
|
||||
* Purpose: opens hydraulics solver system
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -92,8 +95,8 @@ void inithyd(Project *pr, int initflag)
|
||||
**--------------------------------------------------------------
|
||||
** Input: initflag > 0 if link flows should be re-initialized
|
||||
** = 0 if not
|
||||
** Output: none
|
||||
** Purpose: initializes hydraulics solver system
|
||||
** Output: none
|
||||
** Purpose: initializes hydraulics solver system
|
||||
**--------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -106,7 +109,7 @@ void inithyd(Project *pr, int initflag)
|
||||
Stank *tank;
|
||||
Slink *link;
|
||||
Spump *pump;
|
||||
|
||||
|
||||
// Initialize tanks
|
||||
for (i = 1; i <= net->Ntanks; i++)
|
||||
{
|
||||
@@ -128,7 +131,7 @@ void inithyd(Project *pr, int initflag)
|
||||
for (i = 1; i <= net->Nlinks; i++)
|
||||
{
|
||||
link = &net->Link[i];
|
||||
|
||||
|
||||
// Initialize status and setting
|
||||
hyd->LinkStatus[i] = link->Status;
|
||||
hyd->LinkSetting[i] = link->Kc;
|
||||
@@ -140,7 +143,7 @@ void inithyd(Project *pr, int initflag)
|
||||
if (
|
||||
(link->Type == PRV || link->Type == PSV
|
||||
|| link->Type == FCV) && (link->Kc != MISSING)
|
||||
) hyd->LinkStatus[i] = ACTIVE;
|
||||
) hyd->LinkStatus[i] = ACTIVE;
|
||||
|
||||
// Initialize flows if necessary
|
||||
if (hyd->LinkStatus[i] <= CLOSED)
|
||||
@@ -170,7 +173,7 @@ void inithyd(Project *pr, int initflag)
|
||||
|
||||
// Re-position hydraulics file
|
||||
if (pr->outfile.Saveflag)
|
||||
{
|
||||
{
|
||||
fseek(out->HydFile,out->HydOffset,SEEK_SET);
|
||||
}
|
||||
|
||||
@@ -185,10 +188,10 @@ void inithyd(Project *pr, int initflag)
|
||||
int runhyd(Project *pr, long *t)
|
||||
/*
|
||||
**--------------------------------------------------------------
|
||||
** Input: none
|
||||
** Input: none
|
||||
** Output: t = pointer to current time (in seconds)
|
||||
** Returns: error code
|
||||
** Purpose: solves network hydraulics in a single time period
|
||||
** Returns: error code
|
||||
** Purpose: solves network hydraulics in a single time period
|
||||
**--------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -199,7 +202,7 @@ int runhyd(Project *pr, long *t)
|
||||
int iter; // Iteration count
|
||||
int errcode; // Error code
|
||||
double relerr; // Solution accuracy
|
||||
|
||||
|
||||
// Find new demands & control actions
|
||||
*t = time->Htime;
|
||||
demands(pr);
|
||||
@@ -212,7 +215,7 @@ int runhyd(Project *pr, long *t)
|
||||
{
|
||||
// Report new status & save results
|
||||
if (rpt->Statflag) writehydstat(pr,iter,relerr);
|
||||
|
||||
|
||||
// If system unbalanced and no extra trials
|
||||
// allowed, then activate the Haltflag
|
||||
if (relerr > hyd->Hacc && hyd->ExtraIter == -1)
|
||||
@@ -229,11 +232,11 @@ int runhyd(Project *pr, long *t)
|
||||
int nexthyd(Project *pr, long *tstep)
|
||||
/*
|
||||
**--------------------------------------------------------------
|
||||
** Input: none
|
||||
** Input: none
|
||||
** Output: tstep = pointer to time step (in seconds)
|
||||
** Returns: error code
|
||||
** Returns: error code
|
||||
** Purpose: finds length of next time step & updates tank
|
||||
** levels and rule-based contol actions
|
||||
** levels and rule-based contol actions
|
||||
**--------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -242,7 +245,7 @@ int nexthyd(Project *pr, long *tstep)
|
||||
|
||||
long hydstep; // Actual time step
|
||||
int errcode = 0; // Error code
|
||||
|
||||
|
||||
// Save current results to hydraulics file and
|
||||
// force end of simulation if Haltflag is active
|
||||
if (pr->outfile.Saveflag) errcode = savehyd(pr, &time->Htime);
|
||||
@@ -277,14 +280,14 @@ int nexthyd(Project *pr, long *tstep)
|
||||
*tstep = hydstep;
|
||||
return errcode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void closehyd(Project *pr)
|
||||
/*
|
||||
**--------------------------------------------------------------
|
||||
** Input: none
|
||||
** Output: returns error code
|
||||
** Purpose: closes hydraulics solver system
|
||||
** Input: none
|
||||
** Output: returns error code
|
||||
** Purpose: closes hydraulics solver system
|
||||
**--------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -296,9 +299,9 @@ void closehyd(Project *pr)
|
||||
int allocmatrix(Project *pr)
|
||||
/*
|
||||
**--------------------------------------------------------------
|
||||
** Input: none
|
||||
** Output: returns error code
|
||||
** Purpose: allocates memory used for solution matrix coeffs.
|
||||
** Input: none
|
||||
** Output: returns error code
|
||||
** Purpose: allocates memory used for solution matrix coeffs.
|
||||
**--------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -306,7 +309,7 @@ int allocmatrix(Project *pr)
|
||||
Hydraul *hyd = &pr->hydraul;
|
||||
|
||||
int errcode = 0;
|
||||
|
||||
|
||||
hyd->P = (double *) calloc(net->Nlinks+1,sizeof(double));
|
||||
hyd->Y = (double *) calloc(net->Nlinks+1,sizeof(double));
|
||||
hyd->DemandFlow = (double *) calloc(net->Nnodes + 1, sizeof(double));
|
||||
@@ -328,14 +331,14 @@ int allocmatrix(Project *pr)
|
||||
void freematrix(Project *pr)
|
||||
/*
|
||||
**--------------------------------------------------------------
|
||||
** Input: none
|
||||
** Output: none
|
||||
** Purpose: frees memory used for solution matrix coeffs.
|
||||
** Input: none
|
||||
** Output: none
|
||||
** Purpose: frees memory used for solution matrix coeffs.
|
||||
**--------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
Hydraul *hyd = &pr->hydraul;
|
||||
|
||||
|
||||
free(hyd->P);
|
||||
free(hyd->Y);
|
||||
free(hyd->DemandFlow);
|
||||
@@ -351,7 +354,7 @@ void initlinkflow(Project *pr, int i, char s, double k)
|
||||
** Input: i = link index
|
||||
** s = link status
|
||||
** k = link setting (i.e., pump speed)
|
||||
** Output: none
|
||||
** Output: none
|
||||
** Purpose: sets initial flow in link to QZERO if link is closed,
|
||||
** to design flow for a pump, or to flow at velocity of
|
||||
** 1 fps for other links.
|
||||
@@ -362,7 +365,7 @@ void initlinkflow(Project *pr, int i, char s, double k)
|
||||
Network *n = &pr->network;
|
||||
|
||||
Slink *link = &n->Link[i];
|
||||
|
||||
|
||||
if (s == CLOSED)
|
||||
{
|
||||
hyd->LinkFlow[i] = QZERO;
|
||||
@@ -383,8 +386,8 @@ void setlinkflow(Project *pr, int k, double dh)
|
||||
**--------------------------------------------------------------
|
||||
** Input: k = link index
|
||||
** dh = head loss across link
|
||||
** Output: none
|
||||
** Purpose: sets flow in link based on current headloss
|
||||
** Output: none
|
||||
** Purpose: sets flow in link based on current headloss
|
||||
**--------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -396,7 +399,7 @@ void setlinkflow(Project *pr, int k, double dh)
|
||||
double x ,y;
|
||||
Slink *link = &net->Link[k];
|
||||
Scurve *curve;
|
||||
|
||||
|
||||
switch (link->Type)
|
||||
{
|
||||
case CVPIPE:
|
||||
@@ -408,7 +411,7 @@ void setlinkflow(Project *pr, int k, double dh)
|
||||
y = sqrt(ABS(dh) / link->R / 1.32547);
|
||||
hyd->LinkFlow[k] = x * y;
|
||||
}
|
||||
|
||||
|
||||
// For Hazen-Williams or Manning formulas use inverse of formula
|
||||
else
|
||||
{
|
||||
@@ -416,16 +419,16 @@ void setlinkflow(Project *pr, int k, double dh)
|
||||
y = 1.0 / hyd->Hexp;
|
||||
hyd->LinkFlow[k] = pow(x, y);
|
||||
}
|
||||
|
||||
|
||||
// Change sign of flow to match sign of head loss
|
||||
if (dh < 0.0) hyd->LinkFlow[k] = -hyd->LinkFlow[k];
|
||||
break;
|
||||
|
||||
|
||||
case PUMP:
|
||||
// Convert headloss to pump head gain
|
||||
dh = -dh;
|
||||
p = findpump(net, k);
|
||||
|
||||
|
||||
// For custom pump curve, interpolate from curve
|
||||
if (net->Pump[p].Ptype == CUSTOM)
|
||||
{
|
||||
@@ -435,7 +438,7 @@ void setlinkflow(Project *pr, int k, double dh)
|
||||
hyd->LinkFlow[k] = interp(curve->Npts, curve->Y, curve->X, dh) *
|
||||
hyd->LinkSetting[k] / pr->Ucf[FLOW];
|
||||
}
|
||||
|
||||
|
||||
// Otherwise use inverse of power curve
|
||||
else
|
||||
{
|
||||
@@ -459,7 +462,7 @@ void setlinkstatus(Project *pr, int index, char value, StatusType *s, double *k
|
||||
** s = pointer to link status
|
||||
** k = pointer to link setting
|
||||
** Output: none
|
||||
** Purpose: sets link status to OPEN or CLOSED
|
||||
** Purpose: sets link status to OPEN or CLOSED
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -467,11 +470,11 @@ void setlinkstatus(Project *pr, int index, char value, StatusType *s, double *k
|
||||
|
||||
Slink *link = &net->Link[index];
|
||||
LinkType t = link->Type;
|
||||
|
||||
// Status set to open
|
||||
|
||||
// Status set to open
|
||||
if (value == 1)
|
||||
{
|
||||
// Adjust link setting for pumps & valves
|
||||
// Adjust link setting for pumps & valves
|
||||
if (t == PUMP) *k = 1.0;
|
||||
if (t > PUMP && t != GPV) *k = MISSING;
|
||||
|
||||
@@ -479,7 +482,7 @@ void setlinkstatus(Project *pr, int index, char value, StatusType *s, double *k
|
||||
*s = OPEN;
|
||||
}
|
||||
|
||||
// Status set to closed
|
||||
// Status set to closed
|
||||
else if (value == 0)
|
||||
{
|
||||
// Adjust link setting for pumps & valves
|
||||
@@ -509,7 +512,7 @@ void setlinksetting(Project *pr, int index, double value, StatusType *s,
|
||||
|
||||
Slink *link = &net->Link[index];
|
||||
LinkType t = link->Type;
|
||||
|
||||
|
||||
// For a pump, status is OPEN if speed > 0, CLOSED otherwise
|
||||
if (t == PUMP)
|
||||
{
|
||||
@@ -531,15 +534,15 @@ void setlinksetting(Project *pr, int index, double value, StatusType *s,
|
||||
if (*k == MISSING && *s <= CLOSED) *s = OPEN;
|
||||
*k = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void demands(Project *pr)
|
||||
/*
|
||||
**--------------------------------------------------------------------
|
||||
** Input: none
|
||||
** Output: none
|
||||
** Purpose: computes demands at nodes during current time period
|
||||
** Input: none
|
||||
** Output: none
|
||||
** Purpose: computes demands at nodes during current time period
|
||||
**--------------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -610,9 +613,9 @@ void demands(Project *pr)
|
||||
int controls(Project *pr)
|
||||
/*
|
||||
**---------------------------------------------------------------------
|
||||
** Input: none
|
||||
** Output: number of links whose setting changes
|
||||
** Purpose: implements simple controls based on time or tank levels
|
||||
** Input: none
|
||||
** Output: number of links whose setting changes
|
||||
** Purpose: implements simple controls based on time or tank levels
|
||||
**---------------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -626,7 +629,7 @@ int controls(Project *pr)
|
||||
double k1, k2;
|
||||
char s1, s2;
|
||||
Slink *link;
|
||||
Scontrol *control;
|
||||
Scontrol *control;
|
||||
|
||||
// Examine each control statement
|
||||
setsum = 0;
|
||||
@@ -680,7 +683,7 @@ int controls(Project *pr)
|
||||
if (pr->report.Statflag) writecontrolaction(pr,k,i);
|
||||
setsum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return setsum;
|
||||
}
|
||||
@@ -689,9 +692,9 @@ int controls(Project *pr)
|
||||
long timestep(Project *pr)
|
||||
/*
|
||||
**----------------------------------------------------------------
|
||||
** Input: none
|
||||
** Output: returns time step until next change in hydraulics
|
||||
** Purpose: computes time step to advance hydraulic simulation
|
||||
** Input: none
|
||||
** Output: returns time step until next change in hydraulics
|
||||
** Purpose: computes time step to advance hydraulic simulation
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -699,26 +702,26 @@ long timestep(Project *pr)
|
||||
Times *time = &pr->times;
|
||||
|
||||
long n, t, tstep;
|
||||
|
||||
|
||||
// Normal time step is hydraulic time step
|
||||
tstep = time->Hstep;
|
||||
|
||||
|
||||
// Revise time step based on time until next demand period
|
||||
// (n = next pattern period, t = time till next period)
|
||||
n = ((time->Htime + time->Pstart) / time->Pstep) + 1;
|
||||
t = n * time->Pstep - time->Htime;
|
||||
if (t > 0 && t < tstep) tstep = t;
|
||||
|
||||
|
||||
// Revise time step based on time until next reporting period
|
||||
t = time->Rtime - time->Htime;
|
||||
if (t > 0 && t < tstep) tstep = t;
|
||||
|
||||
|
||||
// Revise time step based on smallest time to fill or drain a tank
|
||||
tanktimestep(pr, &tstep);
|
||||
|
||||
|
||||
// Revise time step based on smallest time to activate a control
|
||||
controltimestep(pr, &tstep);
|
||||
|
||||
|
||||
// Evaluate rule-based controls (which will also update tank levels)
|
||||
if (net->Nrules > 0) ruletimestep(pr, &tstep);
|
||||
else tanklevels(pr, tstep);
|
||||
@@ -729,10 +732,10 @@ long timestep(Project *pr)
|
||||
int tanktimestep(Project *pr, long *tstep)
|
||||
/*
|
||||
**-----------------------------------------------------------------
|
||||
** Input: *tstep = current time step
|
||||
** Output: *tstep = modified current time step
|
||||
** Input: *tstep = current time step
|
||||
** Output: *tstep = modified current time step
|
||||
** Purpose: revises time step based on shortest time to fill or
|
||||
** drain a tank
|
||||
** drain a tank
|
||||
**-----------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -777,10 +780,10 @@ int tanktimestep(Project *pr, long *tstep)
|
||||
void controltimestep(Project *pr, long *tstep)
|
||||
/*
|
||||
**------------------------------------------------------------------
|
||||
** Input: *tstep = current time step
|
||||
** Output: *tstep = modified current time step
|
||||
** Input: *tstep = current time step
|
||||
** Output: *tstep = modified current time step
|
||||
** Purpose: revises time step based on shortest time to activate
|
||||
** a simple control
|
||||
** a simple control
|
||||
**------------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -792,24 +795,24 @@ void controltimestep(Project *pr, long *tstep)
|
||||
long t, t1, t2;
|
||||
Slink *link;
|
||||
Scontrol *control;
|
||||
|
||||
|
||||
// Examine each control
|
||||
for (i = 1; i <= net->Ncontrols; i++)
|
||||
{
|
||||
t = 0;
|
||||
control = &net->Control[i];
|
||||
|
||||
// Control depends on a tank level
|
||||
// Control depends on a tank level
|
||||
if ( (n = control->Node) > 0)
|
||||
{
|
||||
// Skip node if not a tank or reservoir
|
||||
if ((j = n - net->Njuncs) <= 0) continue;
|
||||
|
||||
|
||||
// Find current head and flow into tank
|
||||
h = hyd->NodeHead[n];
|
||||
q = hyd->NodeDemand[n];
|
||||
if (ABS(q) <= QZERO) continue;
|
||||
|
||||
|
||||
// Find time to reach upper or lower control level
|
||||
if ( (h < control->Grade && control->Type == HILEVEL && q > 0.0)
|
||||
|| (h > control->Grade && control->Type == LOWLEVEL && q < 0.0) )
|
||||
@@ -821,7 +824,7 @@ void controltimestep(Project *pr, long *tstep)
|
||||
|
||||
// Control is based on elapsed time
|
||||
if (control->Type == TIMER)
|
||||
{
|
||||
{
|
||||
if (control->Time > pr->times.Htime)
|
||||
{
|
||||
t = control->Time - pr->times.Htime;
|
||||
@@ -853,16 +856,16 @@ void controltimestep(Project *pr, long *tstep)
|
||||
void ruletimestep(Project *pr, long *tstep)
|
||||
/*
|
||||
**--------------------------------------------------------------
|
||||
** Input: *tstep = current time step (sec)
|
||||
** Output: *tstep = modified time step
|
||||
** Input: *tstep = current time step (sec)
|
||||
** Output: *tstep = modified time step
|
||||
** Purpose: updates next time step by checking if any rules
|
||||
** will fire before then; also updates tank levels.
|
||||
** will fire before then; also updates tank levels.
|
||||
**--------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
Network *net = &pr->network;
|
||||
Times *time = &pr->times;
|
||||
|
||||
|
||||
long tnow, // Start of time interval for rule evaluation
|
||||
tmax, // End of time interval for rule evaluation
|
||||
dt, // Normal time increment for rule evaluation
|
||||
@@ -880,7 +883,7 @@ void ruletimestep(Project *pr, long *tstep)
|
||||
}
|
||||
|
||||
// Otherwise, time increment equals rule evaluation time step and
|
||||
// first actual increment equals time until next even multiple of
|
||||
// first actual increment equals time until next even multiple of
|
||||
// Rulestep occurs.
|
||||
else
|
||||
{
|
||||
@@ -888,7 +891,7 @@ void ruletimestep(Project *pr, long *tstep)
|
||||
dt1 = time->Rulestep - (tnow % time->Rulestep);
|
||||
}
|
||||
|
||||
// Make sure time increment is no larger than current time step
|
||||
// Make sure time increment is no larger than current time step
|
||||
dt = MIN(dt, *tstep);
|
||||
dt1 = MIN(dt1, *tstep);
|
||||
if (dt1 == 0) dt1 = dt;
|
||||
@@ -918,14 +921,14 @@ void ruletimestep(Project *pr, long *tstep)
|
||||
*tstep = time->Htime - tnow;
|
||||
time->Htime = tnow;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void addenergy(Project *pr, long hstep)
|
||||
/*
|
||||
**-------------------------------------------------------------
|
||||
** Input: hstep = time step (sec)
|
||||
** Output: none
|
||||
** Purpose: accumulates pump energy usage
|
||||
** Input: hstep = time step (sec)
|
||||
** Output: none
|
||||
** Purpose: accumulates pump energy usage
|
||||
**-------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -1003,10 +1006,10 @@ void addenergy(Project *pr, long hstep)
|
||||
void getenergy(Project *pr, int k, double *kw, double *eff)
|
||||
/*
|
||||
**----------------------------------------------------------------
|
||||
** Input: k = link index
|
||||
** Input: k = link index
|
||||
** Output: *kw = kwatt energy used
|
||||
** *eff = efficiency (pumps only)
|
||||
** Purpose: computes flow energy associated with link k
|
||||
** Purpose: computes flow energy associated with link k
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -1022,7 +1025,7 @@ void getenergy(Project *pr, int k, double *kw, double *eff)
|
||||
double speed; // current speed setting
|
||||
Scurve *curve;
|
||||
Slink *link = &net->Link[k];
|
||||
|
||||
|
||||
// No energy if link is closed
|
||||
if (hyd->LinkStatus[k] <= CLOSED)
|
||||
{
|
||||
@@ -1065,10 +1068,10 @@ void getenergy(Project *pr, int k, double *kw, double *eff)
|
||||
void tanklevels(Project *pr, long tstep)
|
||||
/*
|
||||
**----------------------------------------------------------------
|
||||
** Input: tstep = current time step
|
||||
** Output: none
|
||||
** Purpose: computes new water levels in tanks after current
|
||||
** time step
|
||||
** Input: tstep = current time step
|
||||
** Output: none
|
||||
** Purpose: computes new water levels in tanks after current
|
||||
** time step
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -1077,17 +1080,17 @@ void tanklevels(Project *pr, long tstep)
|
||||
|
||||
int i, n;
|
||||
double dv;
|
||||
|
||||
|
||||
for (i = 1; i <= net->Ntanks; i++)
|
||||
{
|
||||
Stank *tank = &net->Tank[i];
|
||||
if (tank->A == 0.0) continue; // Skip reservoirs
|
||||
|
||||
// Update the tank's volume & water elevation
|
||||
|
||||
// Update the tank's volume & water elevation
|
||||
n = tank->Node;
|
||||
dv = hyd->NodeDemand[n] * tstep;
|
||||
tank->V += dv;
|
||||
|
||||
|
||||
// Check if tank full/empty within next second
|
||||
if (tank->V + hyd->NodeDemand[n] >= tank->Vmax)
|
||||
{
|
||||
@@ -1105,10 +1108,10 @@ void tanklevels(Project *pr, long tstep)
|
||||
double tankvolume(Project *pr, int i, double h)
|
||||
/*
|
||||
**--------------------------------------------------------------------
|
||||
** Input: i = tank index
|
||||
** h = water elevation in tank
|
||||
** Output: returns water volume in tank
|
||||
** Purpose: finds water volume in tank i corresponding to elev. h.
|
||||
** Input: i = tank index
|
||||
** h = water elevation in tank
|
||||
** Output: returns water volume in tank
|
||||
** Purpose: finds water volume in tank i corresponding to elev. h.
|
||||
**--------------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -1122,7 +1125,7 @@ double tankvolume(Project *pr, int i, double h)
|
||||
// Use level*area if no volume curve
|
||||
j = tank->Vcurve;
|
||||
if (j == 0) return(tank->Vmin + (h - tank->Hmin) * tank->A);
|
||||
|
||||
|
||||
// If curve exists, interpolate on h to find volume v
|
||||
// remembering that volume curve is in original units.
|
||||
else
|
||||
@@ -1138,10 +1141,10 @@ double tankvolume(Project *pr, int i, double h)
|
||||
double tankgrade(Project *pr, int i, double v)
|
||||
/*
|
||||
**-------------------------------------------------------------------
|
||||
** Input: i = tank index
|
||||
** v = volume in tank
|
||||
** Output: returns water level in tank
|
||||
** Purpose: finds water level in tank i corresponding to volume v.
|
||||
** Input: i = tank index
|
||||
** v = volume in tank
|
||||
** Output: returns water level in tank
|
||||
** Purpose: finds water level in tank i corresponding to volume v.
|
||||
**-------------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
@@ -1154,7 +1157,7 @@ double tankgrade(Project *pr, int i, double v)
|
||||
// Use area if no volume curve
|
||||
j = tank->Vcurve;
|
||||
if (j == 0) return(tank->Hmin + (v - tank->Vmin) / tank->A);
|
||||
|
||||
|
||||
// If curve exists, interpolate on volume (originally the Y-variable
|
||||
// but used here as the X-variable) to find new level above bottom.
|
||||
// Remember that volume curve is stored in original units.
|
||||
|
||||
@@ -12,13 +12,16 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "types.h"
|
||||
@@ -453,7 +456,7 @@ void newlinkflows(Project *pr, Hydbalance *hbal, double *qsum, double *dqsum)
|
||||
hbal->maxflownode = -1;
|
||||
}
|
||||
|
||||
// Update net flows to fixed grade nodes
|
||||
// Update net flows to fixed grade nodes
|
||||
if (hyd->LinkStatus[k] > CLOSED)
|
||||
{
|
||||
if (n1 > net->Njuncs) hyd->NodeDemand[n1] -= hyd->LinkFlow[k];
|
||||
@@ -487,7 +490,7 @@ void newemitterflows(Project *pr, Hydbalance *hbal, double *qsum,
|
||||
// Skip junction if it does not have an emitter
|
||||
if (net->Node[i].Ke == 0.0) continue;
|
||||
|
||||
// Find emitter head loss and gradient
|
||||
// Find emitter head loss and gradient
|
||||
emitheadloss(pr, i, &hloss, &hgrad);
|
||||
|
||||
// Find emitter flow change
|
||||
|
||||
@@ -10,8 +10,15 @@ License: see LICENSE
|
||||
Last Updated: 11/27/2018
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "funcs.h"
|
||||
|
||||
@@ -48,7 +55,7 @@ int valvestatus(Project *pr)
|
||||
n1, n2; // Start & end nodes
|
||||
double hset; // Valve head setting
|
||||
StatusType status; // Valve status settings
|
||||
Slink *link;
|
||||
Slink *link;
|
||||
|
||||
// Examine each valve
|
||||
for (i = 1; i <= net->Nvalves; i++)
|
||||
@@ -59,7 +66,7 @@ int valvestatus(Project *pr)
|
||||
|
||||
// Ignore valve if its status is fixed to OPEN/CLOSED
|
||||
if (hyd->LinkSetting[k] == MISSING) continue;
|
||||
|
||||
|
||||
// Get start/end node indexes & save current status
|
||||
n1 = link->N1;
|
||||
n2 = link->N2;
|
||||
@@ -449,7 +456,7 @@ void tankstatus(Project *pr, int k, int n1, int n2)
|
||||
|
||||
// Case 2: Downstream head > tank head
|
||||
// (e.g., an open outflow check valve would close)
|
||||
else if (cvstatus(pr, OPEN, h, q) == CLOSED)
|
||||
else if (cvstatus(pr, OPEN, h, q) == CLOSED)
|
||||
{
|
||||
hyd->LinkStatus[k] = TEMPCLOSED;
|
||||
}
|
||||
|
||||
@@ -7,17 +7,20 @@ Description: saves network data to an EPANET formatted text file
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 03/17/2019
|
||||
Last Updated: 04/03/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "types.h"
|
||||
@@ -38,7 +41,7 @@ extern char *TstatTxt[];
|
||||
extern char *RptFlagTxt[];
|
||||
extern char *SectTxt[];
|
||||
|
||||
void saveauxdata(Project *pr, FILE *f)
|
||||
void saveauxdata(Project *pr, FILE *f)
|
||||
/*
|
||||
------------------------------------------------------------
|
||||
Writes auxilary data from original input file to new file.
|
||||
@@ -51,7 +54,7 @@ void saveauxdata(Project *pr, FILE *f)
|
||||
char line[MAXLINE + 1];
|
||||
char s[MAXLINE + 1];
|
||||
FILE *InFile = pr->parser.InFile;
|
||||
|
||||
|
||||
// Re-open the input file
|
||||
if (InFile == NULL)
|
||||
{
|
||||
@@ -88,7 +91,7 @@ void saveauxdata(Project *pr, FILE *f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Write line of auxilary data to file
|
||||
else
|
||||
{
|
||||
@@ -147,7 +150,7 @@ int saveinpfile(Project *pr, const char *fname)
|
||||
// Open the new text file
|
||||
if ((f = fopen(fname, "wt")) == NULL) return 302;
|
||||
|
||||
// Write [TITLE] section
|
||||
// Write [TITLE] section
|
||||
fprintf(f, s_TITLE);
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
@@ -205,7 +208,7 @@ int saveinpfile(Project *pr, const char *fname)
|
||||
}
|
||||
}
|
||||
|
||||
// Write [PIPES] section
|
||||
// Write [PIPES] section
|
||||
fprintf(f, "\n\n");
|
||||
fprintf(f, s_PIPES);
|
||||
for (i = 1; i <= net->Nlinks; i++)
|
||||
@@ -244,7 +247,7 @@ int saveinpfile(Project *pr, const char *fname)
|
||||
// Pump has constant power
|
||||
if (pump->Ptype == CONST_HP) sprintf(s1, " POWER %.4f", link->Km);
|
||||
|
||||
// Pump has a head curve
|
||||
// Pump has a head curve
|
||||
else if ((j = pump->Hcurve) > 0)
|
||||
{
|
||||
sprintf(s1, " HEAD %s", net->Curve[j].ID);
|
||||
@@ -539,16 +542,16 @@ int saveinpfile(Project *pr, const char *fname)
|
||||
fprintf(f, "\n ORDER TANK %-.2f", qual->TankOrder);
|
||||
fprintf(f, "\n GLOBAL BULK %-.6f", qual->Kbulk * SECperDAY);
|
||||
fprintf(f, "\n GLOBAL WALL %-.6f", qual->Kwall * SECperDAY);
|
||||
|
||||
|
||||
if (qual->Climit > 0.0)
|
||||
{
|
||||
fprintf(f, "\n LIMITING POTENTIAL %-.6f", qual->Climit);
|
||||
fprintf(f, "\n LIMITING POTENTIAL %-.6f", qual->Climit * pr->Ucf[QUALITY]);
|
||||
}
|
||||
if (qual->Rfactor != MISSING && qual->Rfactor != 0.0)
|
||||
{
|
||||
fprintf(f, "\n ROUGHNESS CORRELATION %-.6f", qual->Rfactor);
|
||||
}
|
||||
|
||||
|
||||
// Pipe-specific parameters
|
||||
for (i = 1; i <= net->Nlinks; i++)
|
||||
{
|
||||
@@ -633,10 +636,6 @@ int saveinpfile(Project *pr, const char *fname)
|
||||
fprintf(f, "\n UNITS %s", FlowUnitsTxt[parser->Flowflag]);
|
||||
fprintf(f, "\n PRESSURE %s", PressUnitsTxt[parser->Pressflag]);
|
||||
fprintf(f, "\n HEADLOSS %s", FormTxt[hyd->Formflag]);
|
||||
if (hyd->DefPat >= 1 && hyd->DefPat <= net->Npats)
|
||||
{
|
||||
fprintf(f, "\n PATTERN %s", net->Pattern[hyd->DefPat].ID);
|
||||
}
|
||||
switch (out->Hydflag)
|
||||
{
|
||||
case USE:
|
||||
@@ -797,8 +796,7 @@ int saveinpfile(Project *pr, const char *fname)
|
||||
saveauxdata(pr, f);
|
||||
|
||||
// Close the new input file
|
||||
fprintf(f, "\n");
|
||||
fprintf(f, s_END);
|
||||
fprintf(f, "\n%s\n", s_END);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
44
src/input1.c
44
src/input1.c
@@ -3,26 +3,31 @@
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Module: input1.c
|
||||
Description: retrieves network data from an EPANET input file
|
||||
Description: retrieves network data from an EPANET input file
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 03/17/2019
|
||||
Last Updated: 04/03/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "funcs.h"
|
||||
#include "hash.h"
|
||||
#include "text.h"
|
||||
#include <math.h>
|
||||
|
||||
|
||||
// Default values
|
||||
#define MAXITER 200 // Default max. # hydraulic iterations
|
||||
@@ -56,7 +61,7 @@ int getdata(Project *pr)
|
||||
int errcode = 0;
|
||||
|
||||
// Assign default data values & reporting options
|
||||
setdefaults(pr);
|
||||
setdefaults(pr);
|
||||
initreport(&pr->report);
|
||||
|
||||
// Read in network data
|
||||
@@ -100,9 +105,10 @@ void setdefaults(Project *pr)
|
||||
parser->Unitsflag = US; // US unit system
|
||||
parser->Flowflag = GPM; // Flow units are gpm
|
||||
parser->Pressflag = PSI; // Pressure units are psi
|
||||
parser->DefPat = 0; // Default demand pattern index
|
||||
out->Hydflag = SCRATCH; // No external hydraulics file
|
||||
rpt->Tstatflag = SERIES; // Generate time series output
|
||||
|
||||
|
||||
hyd->Formflag = HW; // Use Hazen-Williams formula
|
||||
hyd->Htol = HTOL; // Default head tolerance
|
||||
hyd->Qtol = QTOL; // Default flow tolerance
|
||||
@@ -117,7 +123,6 @@ void setdefaults(Project *pr)
|
||||
hyd->ExtraIter = -1; // Stop if network unbalanced
|
||||
hyd->Viscos = MISSING; // Temporary viscosity
|
||||
hyd->SpGrav = SPGRAV; // Default specific gravity
|
||||
hyd->DefPat = 0; // Default demand pattern index
|
||||
hyd->Epat = 0; // No energy price pattern
|
||||
hyd->Ecost = 0.0; // Zero unit energy cost
|
||||
hyd->Dcost = 0.0; // Zero energy demand charge
|
||||
@@ -326,16 +331,13 @@ void adjustdata(Project *pr)
|
||||
}
|
||||
|
||||
// Use default pattern if none assigned to a demand
|
||||
for (i = 1; i <= net->Nnodes; i++)
|
||||
parser->DefPat = findpattern(net, parser->DefPatID);
|
||||
if (parser->DefPat > 0) for (i = 1; i <= net->Nnodes; i++)
|
||||
{
|
||||
node = &net->Node[i];
|
||||
for (demand = node->D; demand != NULL; demand = demand->next)
|
||||
{
|
||||
if (demand->Pat == 0)
|
||||
{
|
||||
demand->Pat = hyd->DefPat;
|
||||
xstrcpy(&demand->Name, "", MAXID);
|
||||
}
|
||||
if (demand->Pat == 0) demand->Pat = parser->DefPat;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,7 +355,7 @@ int inittanks(Project *pr)
|
||||
*/
|
||||
{
|
||||
Network *net = &pr->network;
|
||||
|
||||
|
||||
int i, j, n = 0;
|
||||
double a;
|
||||
int errcode = 0, levelerr;
|
||||
@@ -546,7 +548,7 @@ void convertunits(Project *pr)
|
||||
Slink *link;
|
||||
Spump *pump;
|
||||
Scontrol *control;
|
||||
|
||||
|
||||
// Convert nodal elevations & initial WQ
|
||||
// (WQ source units are converted in QUALITY.C
|
||||
for (i = 1; i <= net->Nnodes; i++)
|
||||
@@ -644,7 +646,7 @@ void convertunits(Project *pr)
|
||||
pump->H0 /= pr->Ucf[HEAD];
|
||||
pump->R *= (pow(pr->Ucf[FLOW], pump->N) / pr->Ucf[HEAD]);
|
||||
}
|
||||
|
||||
|
||||
// Convert flow range & max. head units
|
||||
pump->Q0 /= pr->Ucf[FLOW];
|
||||
pump->Qmax /= pr->Ucf[FLOW];
|
||||
@@ -653,7 +655,7 @@ void convertunits(Project *pr)
|
||||
}
|
||||
else
|
||||
{
|
||||
// For flow control valves, convert flow setting
|
||||
// For flow control valves, convert flow setting
|
||||
// while for other valves convert pressure setting
|
||||
link->Diam /= pr->Ucf[DIAM];
|
||||
link->Km = 0.02517 * link->Km / SQR(link->Diam) / SQR(link->Diam);
|
||||
|
||||
358
src/input2.c
358
src/input2.c
@@ -7,16 +7,20 @@ Description: reads and interprets network data from an EPANET input file
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 03/17/2019
|
||||
Last Updated: 04/03/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "types.h"
|
||||
@@ -31,7 +35,6 @@ extern char *SectTxt[]; // Input section keywords (see ENUMSTXT.H)
|
||||
// Exported functions
|
||||
int addnodeID(Network *n, int, char *);
|
||||
int addlinkID(Network *n, int, char *);
|
||||
STmplist *getlistitem(char *, STmplist *);
|
||||
|
||||
// Imported functions
|
||||
extern int powercurve(double, double, double, double, double, double *,
|
||||
@@ -39,8 +42,8 @@ extern int powercurve(double, double, double, double, double, double *,
|
||||
|
||||
// Local functions
|
||||
static int newline(Project *, int, char *);
|
||||
static int addpattern(Parser *, char *);
|
||||
static int addcurve(Parser *, char *);
|
||||
static int addpattern(Network *, char *);
|
||||
static int addcurve(Network *, char *);
|
||||
static int unlinked(Project *);
|
||||
static int getpumpparams(Project *);
|
||||
static void inperrmsg(Project *, int, int, char *);
|
||||
@@ -56,11 +59,12 @@ int netsize(Project *pr)
|
||||
*/
|
||||
{
|
||||
Parser *parser = &pr->parser;
|
||||
|
||||
|
||||
char line[MAXLINE + 1]; // Line from input data file
|
||||
char *tok; // First token of line
|
||||
int sect, newsect; // Input data sections
|
||||
int errcode = 0; // Error code
|
||||
Spattern *pattern;
|
||||
|
||||
// Initialize object counts
|
||||
parser->MaxJuncs = 0;
|
||||
@@ -73,13 +77,20 @@ int netsize(Project *pr)
|
||||
parser->MaxCurves = 0;
|
||||
sect = -1;
|
||||
|
||||
// Add a default demand pattern
|
||||
parser->MaxPats = -1;
|
||||
addpattern(parser,"");
|
||||
|
||||
if (parser->InFile == NULL) return 0;
|
||||
// Add a "dummy" time pattern with index of 0 and a single multiplier
|
||||
// of 1.0 to be used by all demands not assigned a pattern
|
||||
pr->network.Npats = -1;
|
||||
errcode = addpattern(&pr->network, "");
|
||||
if (errcode) return errcode;
|
||||
pattern = &pr->network.Pattern[0];
|
||||
pattern->Length = 1;
|
||||
pattern[0].F = (double *)calloc(1, sizeof(double));
|
||||
pattern[0].F[0] = 1.0;
|
||||
parser->MaxPats = pr->network.Npats;
|
||||
|
||||
// Make a pass through input file counting number of each object
|
||||
if (parser->InFile == NULL) return 0;
|
||||
while (fgets(line, MAXLINE, parser->InFile) != NULL)
|
||||
{
|
||||
// Skip blank lines & those beginning with a comment
|
||||
@@ -111,8 +122,14 @@ int netsize(Project *pr)
|
||||
case _VALVES: parser->MaxValves++; break;
|
||||
case _CONTROLS: parser->MaxControls++; break;
|
||||
case _RULES: addrule(parser,tok); break;
|
||||
case _PATTERNS: errcode = addpattern(parser, tok); break;
|
||||
case _CURVES: errcode = addcurve(parser, tok); break;
|
||||
case _PATTERNS:
|
||||
errcode = addpattern(&pr->network, tok);
|
||||
parser->MaxPats = pr->network.Npats;
|
||||
break;
|
||||
case _CURVES:
|
||||
errcode = addcurve(&pr->network, tok);
|
||||
parser->MaxCurves = pr->network.Ncurves;
|
||||
break;
|
||||
}
|
||||
if (errcode) break;
|
||||
}
|
||||
@@ -162,12 +179,15 @@ int readdata(Project *pr)
|
||||
net->Nvalves = 0;
|
||||
net->Ncontrols = 0;
|
||||
net->Nrules = 0;
|
||||
net->Ncurves = parser->MaxCurves;
|
||||
net->Npats = parser->MaxPats;
|
||||
|
||||
// Patterns & Curves were created previously in netsize()
|
||||
parser->MaxPats = net->Npats;
|
||||
parser->MaxCurves = net->Ncurves;
|
||||
parser->PrevPat = NULL;
|
||||
parser->PrevCurve = NULL;
|
||||
|
||||
// Initialize full line comment, input data section and error count
|
||||
parser->LineComment[0] = '\0';
|
||||
|
||||
sect = -1;
|
||||
errsum = 0;
|
||||
|
||||
@@ -246,16 +266,14 @@ int readdata(Project *pr)
|
||||
// Stop if reach end of file or max. error count
|
||||
if (errsum == MAXERRS) break;
|
||||
}
|
||||
|
||||
|
||||
// Check for errors
|
||||
if (errsum > 0) errcode = 200;
|
||||
|
||||
|
||||
// Check for unlinked nodes
|
||||
if (!errcode) errcode = unlinked(pr);
|
||||
|
||||
// Get pattern & curve data from temporary lists
|
||||
if (!errcode) errcode = getpatterns(pr);
|
||||
if (!errcode) errcode = getcurves(pr);
|
||||
// Determine pump curve parameters
|
||||
if (!errcode) errcode = getpumpparams(pr);
|
||||
|
||||
// Free input buffer
|
||||
@@ -397,7 +415,7 @@ int updatepumpparams(Project *pr, int pumpindex)
|
||||
curve->Type = PUMP_CURVE;
|
||||
npts = curve->Npts;
|
||||
|
||||
// Generic power function curve
|
||||
// Generic power function curve
|
||||
if (npts == 1)
|
||||
{
|
||||
pump->Ptype = POWER_FUNC;
|
||||
@@ -407,7 +425,7 @@ int updatepumpparams(Project *pr, int pumpindex)
|
||||
q2 = 2.0 * q1;
|
||||
h2 = 0.0;
|
||||
}
|
||||
|
||||
|
||||
// 3 point curve with shutoff head
|
||||
else if (npts == 3 && curve->X[0] == 0.0)
|
||||
{
|
||||
@@ -418,7 +436,7 @@ int updatepumpparams(Project *pr, int pumpindex)
|
||||
q2 = curve->X[2];
|
||||
h2 = curve->Y[2];
|
||||
}
|
||||
|
||||
|
||||
// Custom pump curve
|
||||
else
|
||||
{
|
||||
@@ -431,7 +449,7 @@ int updatepumpparams(Project *pr, int pumpindex)
|
||||
pump->Q0 = (curve->X[0] + pump->Qmax) / 2.0;
|
||||
pump->Hmax = curve->Y[0];
|
||||
}
|
||||
|
||||
|
||||
// Compute shape factors & limits of power function curves
|
||||
if (pump->Ptype == POWER_FUNC)
|
||||
{
|
||||
@@ -461,7 +479,7 @@ int addnodeID(Network *net, int n, char *id)
|
||||
**--------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
if (findnode(net,id)) return 0;
|
||||
if (findnode(net,id)) return 0;
|
||||
strncpy(net->Node[n].ID, id, MAXID);
|
||||
hashtable_insert(net->NodeHashTable, net->Node[n].ID, n);
|
||||
return 1;
|
||||
@@ -483,7 +501,7 @@ int addlinkID(Network *net, int n, char *id)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int addpattern(Parser *parser, char *id)
|
||||
int addpattern(Network *network, char *id)
|
||||
/*
|
||||
**-------------------------------------------------------------
|
||||
** Input: id = pattern ID label
|
||||
@@ -492,34 +510,33 @@ int addpattern(Parser *parser, char *id)
|
||||
**--------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
STmplist *patlist;
|
||||
int n = network->Npats;
|
||||
Spattern *pattern;
|
||||
|
||||
// Check if ID is same as last one processed
|
||||
if (parser->Patlist != NULL && strcmp(id, parser->Patlist->ID) == 0) return 0;
|
||||
|
||||
// Check that pattern was not already created
|
||||
if (getlistitem(id, parser->Patlist) == NULL)
|
||||
// Check if pattern was already created
|
||||
if (n > 0)
|
||||
{
|
||||
// Update pattern count & create new list element
|
||||
(parser->MaxPats)++;
|
||||
patlist = (STmplist *)malloc(sizeof(STmplist));
|
||||
if (patlist == NULL) return 101;
|
||||
|
||||
// Initialize list element properties
|
||||
else
|
||||
{
|
||||
patlist->i = parser->MaxPats;
|
||||
strncpy(patlist->ID, id, MAXID);
|
||||
patlist->x = NULL;
|
||||
patlist->y = NULL;
|
||||
patlist->next = parser->Patlist;
|
||||
parser->Patlist = patlist;
|
||||
}
|
||||
if (strcmp(id, network->Pattern[n].ID) == 0) return 0;
|
||||
if (findpattern(network, id) > 0) return 0;
|
||||
}
|
||||
if (strlen(id) > MAXID) return 250;
|
||||
|
||||
// Update pattern count & add a new pattern to the database
|
||||
n = n + 2;
|
||||
network->Pattern = (Spattern *)realloc(network->Pattern, n * sizeof(Spattern));
|
||||
if (network->Pattern == NULL) return 101;
|
||||
(network->Npats)++;
|
||||
|
||||
// Initialize the pattern
|
||||
pattern = &network->Pattern[network->Npats];
|
||||
strncpy(pattern->ID, id, MAXID);
|
||||
pattern->Comment = NULL;
|
||||
pattern->Length = 0;
|
||||
pattern->F = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int addcurve(Parser *parser, char *id)
|
||||
int addcurve(Network *network, char *id)
|
||||
/*
|
||||
**-------------------------------------------------------------
|
||||
** Input: id = curve ID label
|
||||
@@ -528,51 +545,34 @@ int addcurve(Parser *parser, char *id)
|
||||
**--------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
STmplist *curvelist;
|
||||
int n = network->Ncurves;
|
||||
Scurve *curve;
|
||||
|
||||
// Check if ID is same as last one processed
|
||||
if (parser->Curvelist != NULL && strcmp(id, parser->Curvelist->ID) == 0) return 0;
|
||||
|
||||
// Check that curve was not already created
|
||||
if (getlistitem(id, parser->Curvelist) == NULL)
|
||||
// Check if was already created
|
||||
if (n > 0)
|
||||
{
|
||||
// Update curve count & create new list element
|
||||
(parser->MaxCurves)++;
|
||||
curvelist = (STmplist *)malloc(sizeof(STmplist));
|
||||
if (curvelist == NULL) return 101;
|
||||
|
||||
// Initialize list element properties
|
||||
else
|
||||
{
|
||||
curvelist->i = parser->MaxCurves;
|
||||
strncpy(curvelist->ID, id, MAXID);
|
||||
curvelist->x = NULL;
|
||||
curvelist->y = NULL;
|
||||
curvelist->next = parser->Curvelist;
|
||||
parser->Curvelist = curvelist;
|
||||
}
|
||||
if (strcmp(id, network->Curve[n].ID) == 0) return 0;
|
||||
if (findcurve(network, id) > 0) return 0;
|
||||
}
|
||||
if (strlen(id) > MAXID) return 250;
|
||||
|
||||
n = n + 2;
|
||||
network->Curve = (Scurve *)realloc(network->Curve, n * sizeof(Scurve));
|
||||
if (network->Curve == NULL) return 101;
|
||||
(network->Ncurves)++;
|
||||
|
||||
// Initialize the curve
|
||||
curve = &network->Curve[network->Ncurves];
|
||||
strncpy(curve->ID, id, MAXID);
|
||||
curve->Type = GENERIC_CURVE;
|
||||
curve->Comment = NULL;
|
||||
curve->Capacity = 0;
|
||||
curve->Npts = 0;
|
||||
curve->X = NULL;
|
||||
curve->Y = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
STmplist *getlistitem(char *id, STmplist *list)
|
||||
/*
|
||||
**-------------------------------------------------------------
|
||||
** Input: id = ID label
|
||||
** list = pointer to head of a temporary list
|
||||
** Output: returns list item with requested ID label
|
||||
** Purpose: searches for item in temporary list
|
||||
**-------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
STmplist *item;
|
||||
for (item = list; item != NULL; item = item->next)
|
||||
{
|
||||
if (strcmp(item->ID, id) == 0) return item;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int unlinked(Project *pr)
|
||||
/*
|
||||
**--------------------------------------------------------------
|
||||
@@ -587,7 +587,7 @@ int unlinked(Project *pr)
|
||||
Network *net = &pr->network;
|
||||
int *marked;
|
||||
int i, err, errcode;
|
||||
|
||||
|
||||
errcode = 0;
|
||||
err = 0;
|
||||
|
||||
@@ -596,19 +596,19 @@ int unlinked(Project *pr)
|
||||
ERRCODE(MEMCHECK(marked));
|
||||
if (errcode) return errcode;
|
||||
memset(marked, 0, (net->Nnodes + 1) * sizeof(int));
|
||||
|
||||
|
||||
// Mark end nodes of each link
|
||||
for (i = 1; i <= net->Nlinks; i++)
|
||||
{
|
||||
marked[net->Link[i].N1]++;
|
||||
marked[net->Link[i].N2]++;
|
||||
}
|
||||
|
||||
|
||||
// Check each junction
|
||||
for (i = 1; i <= net->Njuncs; i++)
|
||||
{
|
||||
// If not marked then error
|
||||
if (marked[i] == 0)
|
||||
if (marked[i] == 0)
|
||||
{
|
||||
err++;
|
||||
sprintf(pr->Msg, "Error 233: %s %s", geterrmsg(233, pr->Msg), net->Node[i].ID);
|
||||
@@ -621,144 +621,6 @@ int unlinked(Project *pr)
|
||||
return errcode;
|
||||
}
|
||||
|
||||
int getpatterns(Project *pr)
|
||||
/*
|
||||
**-----------------------------------------------------------
|
||||
** Input: none
|
||||
** Output: returns error code
|
||||
** Purpose: retrieves pattern data from temporary linked list
|
||||
**-------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
Network *net = &pr->network;
|
||||
Hydraul *hyd = &pr->hydraul;
|
||||
Parser *parser = &pr->parser;
|
||||
|
||||
int i, j;
|
||||
SFloatlist *f;
|
||||
STmplist *tmppattern;
|
||||
Spattern *pattern;
|
||||
|
||||
// Start at head of the list of patterns
|
||||
tmppattern = parser->Patlist;
|
||||
|
||||
// Traverse list of temporary patterns
|
||||
while (tmppattern != NULL)
|
||||
{
|
||||
// Get index of temporary pattern in network's Pattern array
|
||||
i = tmppattern->i;
|
||||
|
||||
// Check if this is the default pattern
|
||||
if (strcmp(tmppattern->ID, parser->DefPatID) == 0) hyd->DefPat = i;
|
||||
|
||||
// Copy temporary patttern to network's pattern
|
||||
if (i >= 0 && i <= parser->MaxPats)
|
||||
{
|
||||
pattern = &net->Pattern[i];
|
||||
strcpy(pattern->ID, tmppattern->ID);
|
||||
|
||||
/* Give pattern a length of at least 1 */
|
||||
if (pattern->Length == 0) pattern->Length = 1;
|
||||
|
||||
// Allocate array of pattern factors
|
||||
pattern->F = (double *)calloc(pattern->Length, sizeof(double));
|
||||
if (pattern->F == NULL) return 101;
|
||||
|
||||
// Start at head of temporary pattern multiplier list
|
||||
// (which holds multipliers in reverse order)
|
||||
f = tmppattern->x;
|
||||
j = pattern->Length - 1;
|
||||
|
||||
// Use at least one multiplier equal to 1.0
|
||||
if (f == NULL) pattern->F[0] = 1.0;
|
||||
|
||||
// Traverse temporary multiplier list, copying Pattern array */
|
||||
else while (f != NULL && j >= 0)
|
||||
{
|
||||
pattern->F[j] = f->value;
|
||||
f = f->next;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
tmppattern = tmppattern->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getcurves(Project *pr)
|
||||
/*
|
||||
**-----------------------------------------------------------
|
||||
** Input: none
|
||||
** Output: returns error code
|
||||
** Purpose: retrieves curve data from temporary linked list
|
||||
**-----------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
Network *net = &pr->network;
|
||||
Parser *parser = &pr->parser;
|
||||
|
||||
int i, j;
|
||||
double x;
|
||||
char errmsg[MAXMSG+1];
|
||||
SFloatlist *fx, *fy;
|
||||
STmplist *tmpcurve;
|
||||
Scurve *curve;
|
||||
|
||||
// Traverse list of temporary curves
|
||||
tmpcurve = parser->Curvelist;
|
||||
while (tmpcurve != NULL)
|
||||
{
|
||||
// Get index of temporary curve in network's Curve array
|
||||
i = tmpcurve->i;
|
||||
|
||||
// Copy temporary curve to network's curve
|
||||
if (i >= 1 && i <= parser->MaxCurves)
|
||||
{
|
||||
curve = &net->Curve[i];
|
||||
strcpy(curve->ID, tmpcurve->ID);
|
||||
|
||||
// Check that network curve has data points
|
||||
if (curve->Npts <= 0)
|
||||
{
|
||||
sprintf(pr->Msg, "Error 230: %s %s", geterrmsg(230, errmsg), curve->ID);
|
||||
writeline(pr, pr->Msg);
|
||||
return 200;
|
||||
}
|
||||
|
||||
// Allocate memory for network's curve data
|
||||
curve->X = (double *)calloc(curve->Npts, sizeof(double));
|
||||
curve->Y = (double *)calloc(curve->Npts, sizeof(double));
|
||||
if (curve->X == NULL || curve->Y == NULL) return 101;
|
||||
|
||||
// Traverse list of x,y data
|
||||
x = BIG;
|
||||
fx = tmpcurve->x;
|
||||
fy = tmpcurve->y;
|
||||
j = curve->Npts - 1;
|
||||
while (fx != NULL && fy != NULL && j >= 0)
|
||||
{
|
||||
// Check that x data is in ascending order
|
||||
if (fx->value >= x)
|
||||
{
|
||||
sprintf(pr->Msg, "Error 230: %s %s", geterrmsg(230, errmsg), curve->ID);
|
||||
writeline(pr, pr->Msg);
|
||||
return 200;
|
||||
}
|
||||
x = fx->value;
|
||||
|
||||
// Copy x,y data to network's curve
|
||||
curve->X[j] = fx->value;
|
||||
fx = fx->next;
|
||||
curve->Y[j] = fy->value;
|
||||
fy = fy->next;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
tmpcurve = tmpcurve->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int findmatch(char *line, char *keyword[])
|
||||
/*
|
||||
**--------------------------------------------------------------
|
||||
@@ -824,17 +686,17 @@ int gettokens(char *s, char** Tok, int maxToks, char *comment)
|
||||
**--------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int m, n;
|
||||
size_t len;
|
||||
int n;
|
||||
size_t len, m;
|
||||
char *c, *c2;
|
||||
|
||||
|
||||
// clear comment
|
||||
comment[0] = '\0';
|
||||
|
||||
|
||||
// Begin with no tokens
|
||||
for (n=0; n<maxToks; n++) Tok[n] = NULL;
|
||||
n = 0;
|
||||
|
||||
|
||||
// Truncate s at start of comment
|
||||
c = strchr(s,';');
|
||||
if (c)
|
||||
@@ -855,11 +717,17 @@ int gettokens(char *s, char** Tok, int maxToks, char *comment)
|
||||
*c = '\0';
|
||||
}
|
||||
len = (int)strlen(s);
|
||||
|
||||
|
||||
// Scan s for tokens until nothing left
|
||||
while (len > 0 && n < MAXTOKS)
|
||||
{
|
||||
m = (int)strcspn(s,SEPSTR); // Find token length
|
||||
if (m == len) // s is last token
|
||||
{
|
||||
Tok[n] = s;
|
||||
n++;
|
||||
break;
|
||||
}
|
||||
len -= m+1; // Update length of s
|
||||
if (m == 0) s++; // No token found
|
||||
else
|
||||
@@ -868,7 +736,7 @@ int gettokens(char *s, char** Tok, int maxToks, char *comment)
|
||||
{
|
||||
s++; // Start token after quote
|
||||
m = (int)strcspn(s,"\"\n\r"); // Find end quote (or EOL)
|
||||
}
|
||||
}
|
||||
s[m] = '\0'; // Null-terminate the token
|
||||
Tok[n] = s; // Save pointer to token
|
||||
n++; // Update token count
|
||||
@@ -876,7 +744,7 @@ int gettokens(char *s, char** Tok, int maxToks, char *comment)
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
double hour(char *time, char *units)
|
||||
/*
|
||||
@@ -914,7 +782,7 @@ double hour(char *time, char *units)
|
||||
if (match(units, w_DAYS)) return (y[0] * 24.0);
|
||||
}
|
||||
|
||||
// Convert hh:mm:ss format to decimal hours
|
||||
// Convert hh:mm:ss format to decimal hours
|
||||
if (n > 1) y[0] = y[0] + y[1] / 60.0 + y[2] / 3600.0;
|
||||
|
||||
// If am/pm attached then adjust hour accordingly
|
||||
@@ -933,7 +801,7 @@ double hour(char *time, char *units)
|
||||
else return (y[0] + 12.0);
|
||||
}
|
||||
return -1.0;
|
||||
}
|
||||
}
|
||||
|
||||
int getfloat(char *s, double *y)
|
||||
/*
|
||||
@@ -979,14 +847,14 @@ void inperrmsg(Project *pr, int err, int sect, char *line)
|
||||
*/
|
||||
{
|
||||
Parser *parser = &pr->parser;
|
||||
|
||||
|
||||
char errStr[MAXMSG + 1] = "";
|
||||
char tok[MAXMSG + 1];
|
||||
|
||||
// Get token associated with input error
|
||||
if (parser->ErrTok >= 0) strcpy(tok, parser->Tok[parser->ErrTok]);
|
||||
else strcpy(tok, "");
|
||||
|
||||
|
||||
// write error message to report file
|
||||
sprintf(pr->Msg, "Error %d: %s %s in %s section:",
|
||||
err, geterrmsg(err, errStr), tok, SectTxt[sect]);
|
||||
|
||||
216
src/input3.c
216
src/input3.c
@@ -7,16 +7,20 @@ Description: parses network data from a line of an EPANET input file
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 03/17/2019
|
||||
Last Updated: 04/03/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "types.h"
|
||||
@@ -36,7 +40,6 @@ int powercurve(double, double, double, double, double, double *, double *,
|
||||
// Imported Functions
|
||||
extern int addnodeID(Network *, int, char *);
|
||||
extern int addlinkID(Network *, int, char *);
|
||||
extern STmplist *getlistitem(char *, STmplist *);
|
||||
|
||||
// Local functions
|
||||
static int optionchoice(Project *, int);
|
||||
@@ -83,7 +86,6 @@ int juncdata(Project *pr)
|
||||
double el, // elevation
|
||||
y = 0.0; // base demand
|
||||
Pdemand demand; // demand record
|
||||
STmplist *patlist; // list of demands
|
||||
Snode *node;
|
||||
|
||||
// Add new junction to data base
|
||||
@@ -100,9 +102,8 @@ int juncdata(Project *pr)
|
||||
if (n >= 3 && !getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
|
||||
if (n >= 4)
|
||||
{
|
||||
patlist = getlistitem(parser->Tok[3], parser->Patlist);
|
||||
if (patlist == NULL) return setError(parser, 3, 205);
|
||||
p = patlist->i;
|
||||
p = findpattern(net, parser->Tok[3]);
|
||||
if (p == 0) return setError(parser, 3, 205);
|
||||
}
|
||||
|
||||
// Save junction data
|
||||
@@ -158,7 +159,6 @@ int tankdata(Project *pr)
|
||||
minvol = 0.0, // Minimum volume
|
||||
diam = 0.0, // Diameter
|
||||
area; // X-sect. area
|
||||
STmplist *tmplist;
|
||||
Snode *node;
|
||||
Stank *tank;
|
||||
|
||||
@@ -182,9 +182,8 @@ int tankdata(Project *pr)
|
||||
// Head pattern supplied
|
||||
if (n == 3)
|
||||
{
|
||||
tmplist = getlistitem(parser->Tok[2], parser->Patlist);
|
||||
if (tmplist == NULL) return setError(parser, 2, 205);
|
||||
pattern = tmplist->i;
|
||||
pattern = findpattern(net, parser->Tok[2]);
|
||||
if (pattern == 0) return setError(parser, 2, 205);
|
||||
}
|
||||
}
|
||||
else if (n < 6) return 201;
|
||||
@@ -201,9 +200,8 @@ int tankdata(Project *pr)
|
||||
// If volume curve supplied check it exists
|
||||
if (n == 8)
|
||||
{
|
||||
tmplist = getlistitem(parser->Tok[7], parser->Curvelist);
|
||||
if (tmplist == NULL) return setError(parser, 7, 206);
|
||||
curve = tmplist->i;
|
||||
curve = findcurve(net, parser->Tok[7]);
|
||||
if (curve == 0) return setError(parser, 7, 206);
|
||||
net->Curve[curve].Type = VOLUME_CURVE;
|
||||
}
|
||||
if (initlevel < 0.0) return setError(parser, 2, 209);
|
||||
@@ -353,12 +351,12 @@ int pumpdata(Project *pr)
|
||||
Network *net = &pr->network;
|
||||
Parser *parser = &pr->parser;
|
||||
|
||||
int j,
|
||||
int j, m, // Token array indexes
|
||||
j1, // Start-node index
|
||||
j2, // End-node index
|
||||
m, n; // # data items
|
||||
n, // # data items
|
||||
c, p; // Curve & Pattern indexes
|
||||
double y;
|
||||
STmplist *tmplist; // Temporary list
|
||||
Slink *link;
|
||||
Spump *pump;
|
||||
|
||||
@@ -428,15 +426,15 @@ int pumpdata(Project *pr)
|
||||
}
|
||||
else if (match(parser->Tok[m - 1], w_HEAD)) // Custom pump curve
|
||||
{
|
||||
tmplist = getlistitem(parser->Tok[m], parser->Curvelist);
|
||||
if (tmplist == NULL) return setError(parser, m, 206);
|
||||
pump->Hcurve = tmplist->i;
|
||||
c = findcurve(net, parser->Tok[m]);
|
||||
if (c == 0) return setError(parser, m, 206);
|
||||
pump->Hcurve = c;
|
||||
}
|
||||
else if (match(parser->Tok[m - 1], w_PATTERN)) // Speed/status pattern
|
||||
{
|
||||
tmplist = getlistitem(parser->Tok[m], parser->Patlist);
|
||||
if (tmplist == NULL) return setError(parser, m, 205);
|
||||
pump->Upat = tmplist->i;
|
||||
p = findpattern(net, parser->Tok[m]);
|
||||
if (p == 0) return setError(parser, m, 205);
|
||||
pump->Upat = p;
|
||||
}
|
||||
else if (match(parser->Tok[m - 1], w_SPEED)) // Speed setting
|
||||
{
|
||||
@@ -465,7 +463,8 @@ int valvedata(Project *pr)
|
||||
Network *net = &pr->network;
|
||||
Parser *parser = &pr->parser;
|
||||
|
||||
int j1, // Start-node index
|
||||
int c, // Curve index
|
||||
j1, // Start-node index
|
||||
j2, // End-node index
|
||||
n; // # data items
|
||||
char status = ACTIVE, // Valve status
|
||||
@@ -473,7 +472,6 @@ int valvedata(Project *pr)
|
||||
double diam = 0.0, // Valve diameter
|
||||
setting, // Valve setting
|
||||
lcoeff = 0.0; // Minor loss coeff.
|
||||
STmplist *tmplist; // Temporary list
|
||||
Slink *link;
|
||||
|
||||
// Add new valve to data base
|
||||
@@ -504,10 +502,10 @@ int valvedata(Project *pr)
|
||||
// Find headloss curve for GPV
|
||||
if (type == GPV)
|
||||
{
|
||||
tmplist = getlistitem(parser->Tok[5], parser->Curvelist);
|
||||
if (tmplist == NULL) return setError(parser, 5, 206);
|
||||
setting = tmplist->i;
|
||||
net->Curve[tmplist->i].Type = HLOSS_CURVE;
|
||||
c = findcurve(net, parser->Tok[5]);
|
||||
if (c == 0) return setError(parser, 5, 206);
|
||||
setting = c;
|
||||
net->Curve[c].Type = HLOSS_CURVE;
|
||||
status = OPEN;
|
||||
}
|
||||
else if (!getfloat(parser->Tok[5], &setting)) return setError(parser, 5, 202);
|
||||
@@ -554,43 +552,47 @@ int patterndata(Project *pr)
|
||||
Network *net = &pr->network;
|
||||
Parser *parser = &pr->parser;
|
||||
|
||||
int i, n;
|
||||
int i, j, n, n1;
|
||||
double x;
|
||||
SFloatlist *f;
|
||||
STmplist *p;
|
||||
Spattern *pattern;
|
||||
|
||||
// "n" is the number of pattern factors contained in the line
|
||||
n = parser->Ntokens - 1;
|
||||
if (n < 1) return 201;
|
||||
|
||||
// Check for a new pattern
|
||||
if (parser->PrevPat != NULL &&
|
||||
strcmp(parser->Tok[0], parser->PrevPat->ID) == 0) p = parser->PrevPat;
|
||||
// Check if previous input line was for the same pattern
|
||||
if (parser->PrevPat && strcmp(parser->Tok[0], parser->PrevPat->ID) == 0)
|
||||
{
|
||||
pattern = parser->PrevPat;
|
||||
}
|
||||
|
||||
// Otherwise retrieve pattern from the network's Pattern array
|
||||
else
|
||||
{
|
||||
p = getlistitem(parser->Tok[0], parser->Patlist);
|
||||
if (p == NULL) return setError(parser, 0, 205);
|
||||
pattern = &(net->Pattern[p->i]);
|
||||
pattern->Comment = xstrcpy(&pattern->Comment, parser->Comment, MAXMSG);
|
||||
i = findpattern(net, parser->Tok[0]);
|
||||
if (i == 0) return setError(parser, 0, 205);
|
||||
pattern = &(net->Pattern[i]);
|
||||
if (pattern->Comment == NULL && parser->Comment[0])
|
||||
{
|
||||
pattern->Comment = xstrcpy(&pattern->Comment, parser->Comment, MAXMSG);
|
||||
}
|
||||
}
|
||||
|
||||
// Expand size of the pattern's factors array
|
||||
n1 = pattern->Length;
|
||||
pattern->Length += n;
|
||||
pattern->F = realloc(pattern->F, pattern->Length * sizeof(double));
|
||||
|
||||
// Add parsed multipliers to the pattern
|
||||
for (i = 1; i <= n; i++)
|
||||
for (j = 1; j <= n; j++)
|
||||
{
|
||||
if (!getfloat(parser->Tok[i], &x)) return setError(parser, i, 202);
|
||||
f = (SFloatlist *)malloc(sizeof(SFloatlist));
|
||||
if (f == NULL) return 101;
|
||||
f->value = x;
|
||||
f->next = p->x;
|
||||
p->x = f;
|
||||
if (!getfloat(parser->Tok[j], &x)) return setError(parser, j, 202);
|
||||
pattern->F[n1 + j - 1] = x;
|
||||
}
|
||||
|
||||
// Save # multipliers for pattern
|
||||
net->Pattern[p->i].Length += n;
|
||||
|
||||
// Set previous pattern pointer
|
||||
parser->PrevPat = p;
|
||||
return (0);
|
||||
// Save a reference to this pattern for processing additional pattern data
|
||||
parser->PrevPat = pattern;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int curvedata(Project *pr)
|
||||
@@ -608,46 +610,46 @@ int curvedata(Project *pr)
|
||||
Network *net = &pr->network;
|
||||
Parser *parser = &pr->parser;
|
||||
|
||||
int i;
|
||||
double x, y;
|
||||
SFloatlist *fx, *fy;
|
||||
STmplist *c;
|
||||
Scurve *curve;
|
||||
|
||||
// Check for valid curve ID
|
||||
if (parser->Ntokens < 3) return 201;
|
||||
if (parser->PrevCurve != NULL &&
|
||||
strcmp(parser->Tok[0], parser->PrevCurve->ID) == 0) c = parser->PrevCurve;
|
||||
else
|
||||
{
|
||||
c = getlistitem(parser->Tok[0], parser->Curvelist);
|
||||
if (c == NULL) return setError(parser, 0, 206);
|
||||
curve = &(net->Curve[c->i]);
|
||||
curve->Comment = xstrcpy(&curve->Comment, parser->Comment, MAXMSG);
|
||||
}
|
||||
|
||||
// Check for valid data
|
||||
if (parser->Ntokens < 3) return 201;
|
||||
if (!getfloat(parser->Tok[1], &x)) return setError(parser, 1, 202);
|
||||
if (!getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202);
|
||||
|
||||
// Add new data point to curve
|
||||
fx = (SFloatlist *)malloc(sizeof(SFloatlist));
|
||||
if (fx == NULL) return 101;
|
||||
fy = (SFloatlist *)malloc(sizeof(SFloatlist));
|
||||
if (fy == NULL)
|
||||
// Check if previous input line was for the same curve
|
||||
if (parser->PrevCurve && strcmp(parser->Tok[0], parser->PrevCurve->ID) == 0)
|
||||
{
|
||||
free(fx);
|
||||
return 101;
|
||||
curve = parser->PrevCurve;
|
||||
}
|
||||
fx->value = x;
|
||||
fx->next = c->x;
|
||||
c->x = fx;
|
||||
fy->value = y;
|
||||
fy->next = c->y;
|
||||
c->y = fy;
|
||||
net->Curve[c->i].Npts++;
|
||||
|
||||
// Save the pointer to this curve
|
||||
parser->PrevCurve = c;
|
||||
// Otherwise retrieve curve from the network's Curve array
|
||||
else
|
||||
{
|
||||
i = findcurve(net, parser->Tok[0]);
|
||||
if (i == 0) return setError(parser, 0, 206);
|
||||
curve = &(net->Curve[i]);
|
||||
if (curve->Comment == NULL && parser->Comment[0])
|
||||
{
|
||||
curve->Comment = xstrcpy(&curve->Comment, parser->Comment, MAXMSG);
|
||||
}
|
||||
}
|
||||
|
||||
// Expand size of data arrays if need be
|
||||
if (curve->Capacity == curve->Npts)
|
||||
{
|
||||
if (resizecurve(curve, curve->Capacity + 10) > 0) return 101;
|
||||
}
|
||||
|
||||
// Add new data point to curve
|
||||
curve->X[curve->Npts] = x;
|
||||
curve->Y[curve->Npts] = y;
|
||||
curve->Npts++;
|
||||
|
||||
// Save a reference to this curve for processing additional curve data
|
||||
parser->PrevCurve = curve;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -709,7 +711,6 @@ int demanddata(Project *pr)
|
||||
double y;
|
||||
Pdemand demand;
|
||||
Pdemand cur_demand;
|
||||
STmplist *patlist;
|
||||
|
||||
// Extract data from tokens
|
||||
n = parser->Ntokens;
|
||||
@@ -729,9 +730,8 @@ int demanddata(Project *pr)
|
||||
if (j > net->Njuncs) return 0;
|
||||
if (n >= 3)
|
||||
{
|
||||
patlist = getlistitem(parser->Tok[2], parser->Patlist);
|
||||
if (patlist == NULL) return setError(parser, 2, 205);
|
||||
p = patlist->i;
|
||||
p = findpattern(net, parser->Tok[2]);
|
||||
if (p == 0) return setError(parser, 2, 205);
|
||||
}
|
||||
|
||||
// Replace any demand entered in [JUNCTIONS] section
|
||||
@@ -742,7 +742,10 @@ int demanddata(Project *pr)
|
||||
// with what is specified in this section
|
||||
demand->Base = y;
|
||||
demand->Pat = p;
|
||||
demand->Name = xstrcpy(&demand->Name, parser->Comment, MAXID);
|
||||
if (parser->Comment[0])
|
||||
{
|
||||
demand->Name = xstrcpy(&demand->Name, parser->Comment, MAXID);
|
||||
}
|
||||
hyd->NodeDemand[j] = MISSING; // marker - next iteration will append a new category.
|
||||
}
|
||||
|
||||
@@ -755,7 +758,11 @@ int demanddata(Project *pr)
|
||||
if (demand == NULL) return 101;
|
||||
demand->Base = y;
|
||||
demand->Pat = p;
|
||||
demand->Name = xstrcpy(&demand->Name, parser->Comment, MAXID);
|
||||
demand->Name = NULL;
|
||||
if (parser->Comment[0])
|
||||
{
|
||||
demand->Name = xstrcpy(&demand->Name, parser->Comment, MAXID);
|
||||
}
|
||||
demand->next = NULL;
|
||||
cur_demand->next = demand;
|
||||
}
|
||||
@@ -896,7 +903,6 @@ int sourcedata(Project *pr)
|
||||
p = 0; // Time pattern index
|
||||
char type = CONCEN; // Source type
|
||||
double c0 = 0; // Initial quality
|
||||
STmplist *patlist;
|
||||
Psource source;
|
||||
|
||||
// Check for enough tokens & that source node exists
|
||||
@@ -925,9 +931,8 @@ int sourcedata(Project *pr)
|
||||
if (n > i + 1 && strlen(parser->Tok[i + 1]) > 0 &&
|
||||
strcmp(parser->Tok[i + 1], "*") != 0)
|
||||
{
|
||||
patlist = getlistitem(parser->Tok[i + 1], parser->Patlist);
|
||||
if (patlist == NULL) return setError(parser, i+1, 205);
|
||||
p = patlist->i;
|
||||
p = findpattern(net, parser->Tok[i + 1]);
|
||||
if (p == 0) return setError(parser, i + 1, 205);
|
||||
}
|
||||
|
||||
// Destroy any existing source assigned to node
|
||||
@@ -1331,10 +1336,9 @@ int energydata(Project *pr)
|
||||
Hydraul *hyd = &pr->hydraul;
|
||||
Parser *parser = &pr->parser;
|
||||
|
||||
int j, k, n;
|
||||
int j, k, n, p, c;
|
||||
double y;
|
||||
|
||||
STmplist *listitem;
|
||||
Slink *Link = net->Link;
|
||||
Spump *Pump = net->Pump;
|
||||
|
||||
@@ -1381,10 +1385,10 @@ int energydata(Project *pr)
|
||||
// Price PATTERN being set
|
||||
else if (match(parser->Tok[n - 2], w_PATTERN))
|
||||
{
|
||||
listitem = getlistitem(parser->Tok[n - 1], parser->Patlist);
|
||||
if (listitem == NULL) return setError(parser, n - 1, 205);
|
||||
if (j == 0) hyd->Epat = listitem->i;
|
||||
else Pump[j].Epat = listitem->i;
|
||||
p = findpattern(net, parser->Tok[n - 1]);
|
||||
if (p == 0) return setError(parser, n - 1, 205);
|
||||
if (j == 0) hyd->Epat = p;
|
||||
else Pump[j].Epat = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1399,10 +1403,10 @@ int energydata(Project *pr)
|
||||
}
|
||||
else
|
||||
{
|
||||
listitem = getlistitem(parser->Tok[n - 1], parser->Curvelist);
|
||||
if (listitem == NULL) return setError(parser, n - 1, 206);
|
||||
Pump[j].Ecurve = listitem->i;
|
||||
net->Curve[listitem->i].Type = EFFIC_CURVE;
|
||||
c = findcurve(net, parser->Tok[n - 1]);
|
||||
if (c == 0) return setError(parser, n - 1, 206);
|
||||
Pump[j].Ecurve = c;
|
||||
net->Curve[c].Type = EFFIC_CURVE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -14,10 +14,14 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "mempool.h"
|
||||
|
||||
/*
|
||||
|
||||
@@ -21,7 +21,9 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
# configure file groups
|
||||
set(EPANET_OUT_SOURCES src/epanet_output.c
|
||||
../util/errormanager.c)
|
||||
../util/errormanager.c
|
||||
../util/filemanager.c
|
||||
../util/cstr_helper.c)
|
||||
|
||||
|
||||
# the binary output file API
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
//
|
||||
// epanet_output.c -- API for reading results from EPANET binary output file
|
||||
//
|
||||
// Version: 0.30
|
||||
// Date 09/06/2017
|
||||
// Version: 0.40
|
||||
// Date 04/02/2019
|
||||
// 09/06/2017
|
||||
// 06/17/2016
|
||||
// 08/05/2014
|
||||
// 05/21/2014
|
||||
@@ -40,18 +41,13 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "util/errormanager.h"
|
||||
#include "util/filemanager.h"
|
||||
|
||||
#include "epanet_output.h"
|
||||
#include "messages.h"
|
||||
|
||||
|
||||
// NOTE: These depend on machine data model and may change when porting
|
||||
// F_OFF Must be a 8 byte / 64 bit integer for large file support
|
||||
#ifdef _WIN32 // Windows (32-bit and 64-bit)
|
||||
#define F_OFF __int64
|
||||
#else // Other platforms
|
||||
#define F_OFF off_t
|
||||
#endif
|
||||
#define INT4 int // Must be a 4 byte / 32 bit integer type
|
||||
#define REAL4 float // Must be a 4 byte / 32 bit real type
|
||||
#define WORDSIZE 4 // Memory alignment 4 byte word size for both int and real
|
||||
@@ -71,33 +67,28 @@
|
||||
|
||||
// Typedefs for opaque pointer
|
||||
typedef struct data_s {
|
||||
char name[MAXFNAME+1]; // file path/name
|
||||
FILE* file; // FILE structure pointer
|
||||
INT4 nodeCount, tankCount, linkCount, pumpCount, valveCount, nPeriods;
|
||||
F_OFF outputStartPos; // starting file position of output data
|
||||
F_OFF bytesPerPeriod; // bytes saved per simulation time period
|
||||
|
||||
error_handle_t* error_handle;
|
||||
error_handle_t *error_handle;
|
||||
file_handle_t *file_handle;
|
||||
} data_t;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
//-----------------------------------------------------------------------------
|
||||
void errorLookup(int errcode, char* errmsg, int length);
|
||||
int validateFile(ENR_Handle);
|
||||
float getNodeValue(ENR_Handle, int, int, int);
|
||||
float getLinkValue(ENR_Handle, int, int, int);
|
||||
void errorLookup(int errcode, char* errmsg, int length);
|
||||
int validateFile(ENR_Handle);
|
||||
float getNodeValue(ENR_Handle, int, int, int);
|
||||
float getLinkValue(ENR_Handle, int, int, int);
|
||||
|
||||
int _fopen(FILE **f, const char *name, const char *mode);
|
||||
int _fseek(FILE* stream, F_OFF offset, int whence);
|
||||
F_OFF _ftell(FILE* stream);
|
||||
|
||||
float* newFloatArray(int n);
|
||||
int* newIntArray(int n);
|
||||
char* newCharArray(int n);
|
||||
float *newFloatArray(int n);
|
||||
int *newIntArray(int n);
|
||||
char *newCharArray(int n);
|
||||
|
||||
|
||||
int EXPORT_OUT_API ENR_init(ENR_Handle* dp_handle)
|
||||
int EXPORT_OUT_API ENR_init(ENR_Handle *dp_handle)
|
||||
// Purpose: Initialized pointer for the opaque ENR_Handle.
|
||||
//
|
||||
// Returns: Error code 0 on success, -1 on failure
|
||||
@@ -114,6 +105,7 @@ int EXPORT_OUT_API ENR_init(ENR_Handle* dp_handle)
|
||||
|
||||
if (p_data != NULL){
|
||||
p_data->error_handle = create_error_manager(&errorLookup);
|
||||
p_data->file_handle = create_file_manager();
|
||||
*dp_handle = p_data;
|
||||
}
|
||||
else
|
||||
@@ -123,7 +115,7 @@ int EXPORT_OUT_API ENR_init(ENR_Handle* dp_handle)
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
int EXPORT_OUT_API ENR_close(ENR_Handle* p_handle)
|
||||
int EXPORT_OUT_API ENR_close(ENR_Handle *p_handle)
|
||||
/*------------------------------------------------------------------------
|
||||
** Input: *p_handle = pointer to ENR_Handle struct
|
||||
**
|
||||
@@ -143,13 +135,16 @@ int EXPORT_OUT_API ENR_close(ENR_Handle* p_handle)
|
||||
|
||||
p_data = (data_t*)(*p_handle);
|
||||
|
||||
if (p_data == NULL || p_data->file == NULL)
|
||||
if (p_data == NULL || p_data->file_handle == NULL)
|
||||
errorcode = -1;
|
||||
|
||||
else
|
||||
{
|
||||
close_file(p_data->file_handle);
|
||||
|
||||
delete_error_manager(p_data->error_handle);
|
||||
fclose(p_data->file);
|
||||
delete_file_manager(p_data->file_handle);
|
||||
|
||||
free(p_data);
|
||||
|
||||
*p_handle = NULL;
|
||||
@@ -178,23 +173,22 @@ int EXPORT_OUT_API ENR_open(ENR_Handle p_handle, const char* path)
|
||||
if (p_data == NULL) return -1;
|
||||
else
|
||||
{
|
||||
strncpy(p_data->name, path, MAXFNAME);
|
||||
// Attempt to open binary output file for reading only
|
||||
if ((_fopen(&(p_data->file), path, "rb")) != 0) errorcode = 434;
|
||||
if ((open_file(p_data->file_handle, path, "rb")) != 0)
|
||||
errorcode = 434;
|
||||
|
||||
// Perform checks to insure the file is valid
|
||||
else if ((err = validateFile(p_data)) != 0) errorcode = err;
|
||||
|
||||
// If a warning is encountered read file header
|
||||
if (errorcode < 400 ) {
|
||||
|
||||
// read network size
|
||||
fseek(p_data->file, 2*WORDSIZE, SEEK_SET);
|
||||
fread(&(p_data->nodeCount), WORDSIZE, 1, p_data->file);
|
||||
fread(&(p_data->tankCount), WORDSIZE, 1, p_data->file);
|
||||
fread(&(p_data->linkCount), WORDSIZE, 1, p_data->file);
|
||||
fread(&(p_data->pumpCount), WORDSIZE, 1, p_data->file);
|
||||
fread(&(p_data->valveCount), WORDSIZE, 1, p_data->file);
|
||||
seek_file(p_data->file_handle, 2*WORDSIZE, SEEK_SET);
|
||||
read_file(&(p_data->nodeCount), WORDSIZE, 1, p_data->file_handle);
|
||||
read_file(&(p_data->tankCount), WORDSIZE, 1, p_data->file_handle);
|
||||
read_file(&(p_data->linkCount), WORDSIZE, 1, p_data->file_handle);
|
||||
read_file(&(p_data->pumpCount), WORDSIZE, 1, p_data->file_handle);
|
||||
read_file(&(p_data->valveCount), WORDSIZE, 1, p_data->file_handle);
|
||||
|
||||
// Compute positions and offsets for retrieving data
|
||||
// fixed portion of header + title section + filenames + chem names
|
||||
@@ -240,8 +234,8 @@ int EXPORT_OUT_API ENR_getVersion(ENR_Handle p_handle, int* version)
|
||||
if (p_data == NULL) return -1;
|
||||
else
|
||||
{
|
||||
fseek(p_data->file, 1*WORDSIZE, SEEK_SET);
|
||||
if (fread(version, WORDSIZE, 1, p_data->file) != 1)
|
||||
seek_file(p_data->file_handle, 1*WORDSIZE, SEEK_SET);
|
||||
if (read_file(version, WORDSIZE, 1, p_data->file_handle) != 1)
|
||||
errorcode = 436;
|
||||
}
|
||||
|
||||
@@ -319,26 +313,26 @@ int EXPORT_OUT_API ENR_getUnits(ENR_Handle p_handle, ENR_Units code, int* unitFl
|
||||
switch (code)
|
||||
{
|
||||
case ENR_flowUnits:
|
||||
_fseek(p_data->file, 9*WORDSIZE, SEEK_SET);
|
||||
fread(unitFlag, WORDSIZE, 1, p_data->file);
|
||||
seek_file(p_data->file_handle, 9*WORDSIZE, SEEK_SET);
|
||||
read_file(unitFlag, WORDSIZE, 1, p_data->file_handle);
|
||||
break;
|
||||
|
||||
case ENR_pressUnits:
|
||||
_fseek(p_data->file, 10*WORDSIZE, SEEK_SET);
|
||||
fread(unitFlag, WORDSIZE, 1, p_data->file);
|
||||
seek_file(p_data->file_handle, 10*WORDSIZE, SEEK_SET);
|
||||
read_file(unitFlag, WORDSIZE, 1, p_data->file_handle);
|
||||
break;
|
||||
|
||||
case ENR_qualUnits:
|
||||
offset = 7*WORDSIZE;
|
||||
_fseek(p_data->file, offset, SEEK_SET);
|
||||
fread(unitFlag, WORDSIZE, 1, p_data->file);
|
||||
seek_file(p_data->file_handle, offset, SEEK_SET);
|
||||
read_file(unitFlag, WORDSIZE, 1, p_data->file_handle);
|
||||
|
||||
if (*unitFlag == 0) *unitFlag = ENR_NONE;
|
||||
|
||||
else if (*unitFlag == 1) {
|
||||
offset = 15*WORDSIZE + 3*MAXMSG_P1 + 2*(MAXFNAME+1) + MAXID_P1;
|
||||
_fseek(p_data->file, offset, SEEK_SET);
|
||||
fread(temp, MAXID_P1, 1, p_data->file);
|
||||
seek_file(p_data->file_handle, offset, SEEK_SET);
|
||||
read_file(temp, MAXID_P1, 1, p_data->file_handle);
|
||||
|
||||
if (!strcmp(temp, "mg/L")) *unitFlag = ENR_MGL;
|
||||
else *unitFlag = ENR_UGL;
|
||||
@@ -379,18 +373,18 @@ int EXPORT_OUT_API ENR_getTimes(ENR_Handle p_handle, ENR_Time code, int* time)
|
||||
switch (code)
|
||||
{
|
||||
case ENR_reportStart:
|
||||
fseek(p_data->file, 12*WORDSIZE, SEEK_SET);
|
||||
fread(time, WORDSIZE, 1, p_data->file);
|
||||
seek_file(p_data->file_handle, 12*WORDSIZE, SEEK_SET);
|
||||
read_file(time, WORDSIZE, 1, p_data->file_handle);
|
||||
break;
|
||||
|
||||
case ENR_reportStep:
|
||||
fseek(p_data->file, 13*WORDSIZE, SEEK_SET);
|
||||
fread(time, WORDSIZE, 1, p_data->file);
|
||||
seek_file(p_data->file_handle, 13*WORDSIZE, SEEK_SET);
|
||||
read_file(time, WORDSIZE, 1, p_data->file_handle);
|
||||
break;
|
||||
|
||||
case ENR_simDuration:
|
||||
fseek(p_data->file, 14*WORDSIZE, SEEK_SET);
|
||||
fread(time, WORDSIZE, 1, p_data->file);
|
||||
seek_file(p_data->file_handle, 14*WORDSIZE, SEEK_SET);
|
||||
read_file(time, WORDSIZE, 1, p_data->file_handle);
|
||||
break;
|
||||
|
||||
case ENR_numPeriods:
|
||||
@@ -405,7 +399,6 @@ int EXPORT_OUT_API ENR_getTimes(ENR_Handle p_handle, ENR_Time code, int* time)
|
||||
}
|
||||
|
||||
int EXPORT_OUT_API ENR_getChemData(ENR_Handle p_handle, char** name, int* length)
|
||||
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -459,8 +452,8 @@ int EXPORT_OUT_API ENR_getElementName(ENR_Handle p_handle, ENR_ElementType type,
|
||||
|
||||
if (!errorcode)
|
||||
{
|
||||
_fseek(p_data->file, offset, SEEK_SET);
|
||||
fread(temp, 1, MAXID_P1, p_data->file);
|
||||
seek_file(p_data->file_handle, offset, SEEK_SET);
|
||||
read_file(temp, 1, MAXID_P1, p_data->file_handle);
|
||||
|
||||
*name = temp;
|
||||
*length = MAXID_P1;
|
||||
@@ -505,9 +498,9 @@ int EXPORT_OUT_API ENR_getEnergyUsage(ENR_Handle p_handle, int pumpIndex,
|
||||
offset += (pumpIndex - 1)*(WORDSIZE + 6*WORDSIZE);
|
||||
|
||||
// Power summary is 1 int and 6 floats for each pump
|
||||
_fseek(p_data->file, offset, SEEK_SET);
|
||||
fread(linkIndex, WORDSIZE, 1, p_data->file);
|
||||
fread(temp, WORDSIZE, 6, p_data->file);
|
||||
seek_file(p_data->file_handle, offset, SEEK_SET);
|
||||
read_file(linkIndex, WORDSIZE, 1, p_data->file_handle);
|
||||
read_file(temp, WORDSIZE, 6, p_data->file_handle);
|
||||
|
||||
*outValues = temp;
|
||||
*length = NENERGYRESULTS;
|
||||
@@ -541,8 +534,8 @@ int EXPORT_OUT_API ENR_getNetReacts(ENR_Handle p_handle, float** outValues, int*
|
||||
// Reaction summary is 4 floats located right before epilogue.
|
||||
// This offset is relative to the end of the file.
|
||||
offset = - 3*WORDSIZE - 4*WORDSIZE;
|
||||
_fseek(p_data->file, offset, SEEK_END);
|
||||
fread(temp, WORDSIZE, 4, p_data->file);
|
||||
seek_file(p_data->file_handle, offset, SEEK_END);
|
||||
read_file(temp, WORDSIZE, 4, p_data->file_handle);
|
||||
|
||||
*outValues = temp;
|
||||
*length = NREACTRESULTS;
|
||||
@@ -670,8 +663,8 @@ int EXPORT_OUT_API ENR_getNodeAttribute(ENR_Handle p_handle, int periodIndex,
|
||||
// add offset for node and attribute
|
||||
offset += ((attr - 1)*p_data->nodeCount)*WORDSIZE;
|
||||
|
||||
_fseek(p_data->file, offset, SEEK_SET);
|
||||
fread(temp, WORDSIZE, p_data->nodeCount, p_data->file);
|
||||
seek_file(p_data->file_handle, offset, SEEK_SET);
|
||||
read_file(temp, WORDSIZE, p_data->nodeCount, p_data->file_handle);
|
||||
|
||||
*outValueArray = temp;
|
||||
*length = p_data->nodeCount;
|
||||
@@ -720,8 +713,8 @@ int EXPORT_OUT_API ENR_getLinkAttribute(ENR_Handle p_handle, int periodIndex,
|
||||
// add offset for link and attribute
|
||||
offset += ((attr - 1)*p_data->linkCount)*WORDSIZE;
|
||||
|
||||
_fseek(p_data->file, offset, SEEK_SET);
|
||||
fread(temp, WORDSIZE, p_data->linkCount, p_data->file);
|
||||
seek_file(p_data->file_handle, offset, SEEK_SET);
|
||||
read_file(temp, WORDSIZE, p_data->linkCount, p_data->file_handle);
|
||||
|
||||
*outValueArray = temp;
|
||||
*length = p_data->linkCount;
|
||||
@@ -852,16 +845,16 @@ int validateFile(ENR_Handle p_handle)
|
||||
p_data = (data_t*)p_handle;
|
||||
|
||||
// Read magic number from beginning of file
|
||||
fseek(p_data->file, 0L, SEEK_SET);
|
||||
fread(&magic1, WORDSIZE, 1, p_data->file);
|
||||
seek_file(p_data->file_handle, 0L, SEEK_SET);
|
||||
read_file(&magic1, WORDSIZE, 1, p_data->file_handle);
|
||||
|
||||
// Fast forward to end and read file epilogue
|
||||
fseek(p_data->file, -3*WORDSIZE, SEEK_END);
|
||||
fread(&(p_data->nPeriods), WORDSIZE, 1, p_data->file);
|
||||
fread(&hydcode, WORDSIZE, 1, p_data->file);
|
||||
fread(&magic2, WORDSIZE, 1, p_data->file);
|
||||
seek_file(p_data->file_handle, -3*WORDSIZE, SEEK_END);
|
||||
read_file(&(p_data->nPeriods), WORDSIZE, 1, p_data->file_handle);
|
||||
read_file(&hydcode, WORDSIZE, 1, p_data->file_handle);
|
||||
read_file(&magic2, WORDSIZE, 1, p_data->file_handle);
|
||||
|
||||
filepos = _ftell(p_data->file);
|
||||
filepos = tell_file(p_data->file_handle);
|
||||
|
||||
// Is the file an EPANET binary file?
|
||||
if (magic1 != magic2) errorcode = 435;
|
||||
@@ -891,8 +884,8 @@ float getNodeValue(ENR_Handle p_handle, int periodIndex, int nodeIndex,
|
||||
// add byte position for attribute and node
|
||||
offset += ((attr - 1)*p_data->nodeCount + (nodeIndex - 1))*WORDSIZE;
|
||||
|
||||
_fseek(p_data->file, offset, SEEK_SET);
|
||||
fread(&y, WORDSIZE, 1, p_data->file);
|
||||
seek_file(p_data->file_handle, offset, SEEK_SET);
|
||||
read_file(&y, WORDSIZE, 1, p_data->file_handle);
|
||||
|
||||
return y;
|
||||
}
|
||||
@@ -915,56 +908,12 @@ float getLinkValue(ENR_Handle p_handle, int periodIndex, int linkIndex,
|
||||
// add byte position for attribute and link
|
||||
offset += ((attr - 1)*p_data->linkCount + (linkIndex - 1))*WORDSIZE;
|
||||
|
||||
_fseek(p_data->file, offset, SEEK_SET);
|
||||
fread(&y, WORDSIZE, 1, p_data->file);
|
||||
seek_file(p_data->file_handle, offset, SEEK_SET);
|
||||
read_file(&y, WORDSIZE, 1, p_data->file_handle);
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
int _fopen(FILE **f, const char *name, const char *mode) {
|
||||
//
|
||||
// Purpose: Substitute for fopen_s on platforms where it doesn't exist
|
||||
// Note: fopen_s is part of C++11 standard
|
||||
//
|
||||
int ret = 0;
|
||||
#ifdef _WIN32
|
||||
ret = (int)fopen_s(f, name, mode);
|
||||
#else
|
||||
*f = fopen(name, mode);
|
||||
if (!*f)
|
||||
ret = -1;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _fseek(FILE* stream, F_OFF offset, int whence)
|
||||
//
|
||||
// Purpose: Selects platform fseek() for large file support
|
||||
//
|
||||
{
|
||||
#ifdef _WIN32 // Windows (32-bit and 64-bit)
|
||||
#define FSEEK64 _fseeki64
|
||||
#else // Other platforms
|
||||
#define FSEEK64 fseeko
|
||||
#endif
|
||||
|
||||
return FSEEK64(stream, offset, whence);
|
||||
}
|
||||
|
||||
F_OFF _ftell(FILE* stream)
|
||||
//
|
||||
// Purpose: Selects platform ftell() for large file support
|
||||
//
|
||||
{
|
||||
#ifdef _WIN32 // Windows (32-bit and 64-bit)
|
||||
#define FTELL64 _ftelli64
|
||||
#else // Other platforms
|
||||
#define FTELL64 ftello
|
||||
#endif
|
||||
|
||||
return FTELL64(stream);
|
||||
}
|
||||
|
||||
float* newFloatArray(int n)
|
||||
//
|
||||
// Warning: Caller must free memory allocated by this function.
|
||||
|
||||
47
src/output.c
47
src/output.c
@@ -11,13 +11,16 @@ Last Updated: 11/27/2018
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "types.h"
|
||||
@@ -32,7 +35,7 @@ static int savetimestat(Project *, REAL4 *, HdrType);
|
||||
static int savenetreacts(Project *, double, double, double, double);
|
||||
static int saveepilog(Project *);
|
||||
|
||||
// Functions to write/read x[1] to x[n] to/from binary file
|
||||
// Functions to write/read x[1] to x[n] to/from binary file
|
||||
size_t f_save(REAL4 *x, int n, FILE *file)
|
||||
{
|
||||
return fwrite(x + 1, sizeof(REAL4), n, file);
|
||||
@@ -79,7 +82,7 @@ int savenetdata(Project *pr)
|
||||
{
|
||||
// Write integer variables to outFile
|
||||
ibuf[0] = MAGICNUMBER;
|
||||
ibuf[1] = 20012; // keep version at 2.00.12 so that GUI will run
|
||||
ibuf[1] = 20012; // keep version at 2.00.12 so that GUI will run
|
||||
ibuf[2] = net->Nnodes;
|
||||
ibuf[3] = net->Ntanks;
|
||||
ibuf[4] = net->Nlinks;
|
||||
@@ -141,7 +144,7 @@ int savenetdata(Project *pr)
|
||||
x[i] = (REAL4)(net->Node[i].El * pr->Ucf[ELEV]);
|
||||
}
|
||||
f_save(x, net->Nnodes, outFile);
|
||||
|
||||
|
||||
// Save link lengths & diameters to outFile
|
||||
for (i = 1; i <= net->Nlinks; i++)
|
||||
{
|
||||
@@ -185,7 +188,7 @@ int savehyd(Project *pr, long *htime)
|
||||
int errcode = 0;
|
||||
REAL4 *x;
|
||||
FILE *HydFile = out->HydFile;
|
||||
|
||||
|
||||
x = (REAL4 *)calloc(MAX(net->Nnodes, net->Nlinks) + 1, sizeof(REAL4));
|
||||
if (x == NULL) return 101;
|
||||
|
||||
@@ -212,13 +215,13 @@ int savehyd(Project *pr, long *htime)
|
||||
fwrite(x + 1, sizeof(REAL4), net->Nlinks, HydFile);
|
||||
//f_save(x, net->Nlinks, HydFile);
|
||||
|
||||
// Save link status
|
||||
// Save link status
|
||||
for (i = 1; i <= net->Nlinks; i++) x[i] = (REAL4)hyd->LinkStatus[i];
|
||||
fwrite(x + 1, sizeof(REAL4), net->Nlinks, HydFile);
|
||||
//f_save(x, net->Nlinks, HydFile);
|
||||
|
||||
// Save link settings & check for successful write-to-disk
|
||||
// (We assume that if any of the previous fwrites failed,
|
||||
// Save link settings & check for successful write-to-disk
|
||||
// (We assume that if any of the previous fwrites failed,
|
||||
// then this one will also fail.)
|
||||
for (i = 1; i <= net->Nlinks; i++) x[i] = (REAL4)hyd->LinkSetting[i];
|
||||
if (fwrite(x + 1, sizeof(REAL4), net->Nlinks, HydFile) <
|
||||
@@ -354,7 +357,7 @@ int readhyd(Project *pr, long *hydtime)
|
||||
int result = 1;
|
||||
REAL4 *x;
|
||||
FILE *HydFile = out->HydFile;
|
||||
|
||||
|
||||
x = (REAL4 *)calloc(MAX(net->Nnodes, net->Nlinks) + 1, sizeof(REAL4));
|
||||
if (x == NULL) return 0;
|
||||
|
||||
@@ -473,7 +476,7 @@ int nodeoutput(Project *pr, int j, REAL4 *x, double ucf)
|
||||
}
|
||||
}
|
||||
|
||||
// Write x[1] to x[net->Nnodes] to output file
|
||||
// Write x[1] to x[net->Nnodes] to output file
|
||||
if (f_save(x, net->Nnodes, outFile) < (unsigned)net->Nnodes) return 308;
|
||||
return 0;
|
||||
}
|
||||
@@ -497,7 +500,7 @@ int linkoutput(Project *pr, int j, REAL4 *x, double ucf)
|
||||
int i;
|
||||
double a, h, q, f, setting;
|
||||
FILE *outFile = out->TmpOutFile;
|
||||
|
||||
|
||||
// Load computed results (in proper units) into buffer x
|
||||
switch (j)
|
||||
{
|
||||
@@ -631,7 +634,7 @@ int savefinaloutput(Project *pr)
|
||||
int errcode = 0;
|
||||
REAL4 *x;
|
||||
FILE *outFile = out->OutFile;
|
||||
|
||||
|
||||
// Save time series statistic if computed
|
||||
if (rpt->Tstatflag != SERIES && out->TmpOutFile != NULL)
|
||||
{
|
||||
@@ -680,7 +683,7 @@ int savetimestat(Project *pr, REAL4 *x, HdrType objtype)
|
||||
long startbyte, skipbytes;
|
||||
float *stat1, *stat2, xx;
|
||||
FILE *outFile = out->OutFile;
|
||||
|
||||
|
||||
// Compute number of bytes in temp output file to skip over (skipbytes)
|
||||
// when moving from one time period to the next for a particular variable
|
||||
if (objtype == NODEHDR)
|
||||
@@ -722,11 +725,11 @@ int savetimestat(Project *pr, REAL4 *x, HdrType objtype)
|
||||
stat2[i] = MISSING;
|
||||
}
|
||||
|
||||
// Position temp output file at start of output
|
||||
// Position temp output file at start of output
|
||||
fseek(out->TmpOutFile, startbyte + (j - n1) * n * sizeof(REAL4),
|
||||
SEEK_SET);
|
||||
|
||||
// Process each time period
|
||||
// Process each time period
|
||||
for (p = 1; p <= rpt->Nperiods; p++)
|
||||
{
|
||||
// Get output results for time period & update stats
|
||||
@@ -751,7 +754,7 @@ int savetimestat(Project *pr, REAL4 *x, HdrType objtype)
|
||||
}
|
||||
}
|
||||
|
||||
// Advance file to next period
|
||||
// Advance file to next period
|
||||
if (p < rpt->Nperiods) fseek(out->TmpOutFile, skipbytes, SEEK_CUR);
|
||||
}
|
||||
|
||||
@@ -821,7 +824,7 @@ int savenetreacts(Project *pr, double wbulk, double wwall, double wtank, double
|
||||
double t;
|
||||
REAL4 w[4];
|
||||
FILE *outFile = out->OutFile;
|
||||
|
||||
|
||||
if (time->Dur > 0) t = (double)time->Dur / 3600.;
|
||||
else t = 1.;
|
||||
w[0] = (REAL4)(wbulk / t);
|
||||
@@ -846,7 +849,7 @@ int saveepilog(Project *pr)
|
||||
int errcode = 0;
|
||||
INT4 i;
|
||||
FILE *outFile = out->OutFile;
|
||||
|
||||
|
||||
i = rpt->Nperiods;
|
||||
if (fwrite(&i, sizeof(INT4), 1, outFile) < 1) errcode = 308;
|
||||
i = pr->Warnflag;
|
||||
|
||||
164
src/project.c
164
src/project.c
@@ -7,17 +7,19 @@
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 03/17/2019
|
||||
Last Updated: 04/03/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
//*** For the Windows SDK _tempnam function ***//
|
||||
#ifdef _WIN32
|
||||
@@ -174,7 +176,7 @@ int openoutfile(Project *pr)
|
||||
|
||||
// Close output file if already opened
|
||||
closeoutfile(pr);
|
||||
|
||||
|
||||
// If output file name was supplied, then attempt to
|
||||
// open it. Otherwise open a temporary output file.
|
||||
pr->outfile.OutFile = fopen(pr->outfile.OutFname, "w+b");
|
||||
@@ -272,9 +274,6 @@ void initpointers(Project *pr)
|
||||
pr->network.NodeHashTable = NULL;
|
||||
pr->network.LinkHashTable = NULL;
|
||||
|
||||
pr->parser.Patlist = NULL;
|
||||
pr->parser.Curvelist = NULL;
|
||||
|
||||
pr->hydraul.smatrix.Aii = NULL;
|
||||
pr->hydraul.smatrix.Aij = NULL;
|
||||
pr->hydraul.smatrix.F = NULL;
|
||||
@@ -284,7 +283,7 @@ void initpointers(Project *pr)
|
||||
pr->hydraul.smatrix.XLNZ = NULL;
|
||||
pr->hydraul.smatrix.NZSUB = NULL;
|
||||
pr->hydraul.smatrix.LNZ = NULL;
|
||||
|
||||
|
||||
initrules(pr);
|
||||
}
|
||||
|
||||
@@ -315,10 +314,10 @@ int allocdata(Project *pr)
|
||||
if (!errcode)
|
||||
{
|
||||
n = pr->parser.MaxNodes + 1;
|
||||
pr->network.Node = (Snode *)calloc(n, sizeof(Snode));
|
||||
pr->network.Node = (Snode *)calloc(n, sizeof(Snode));
|
||||
pr->hydraul.NodeDemand = (double *)calloc(n, sizeof(double));
|
||||
pr->hydraul.NodeHead = (double *)calloc(n, sizeof(double));
|
||||
pr->quality.NodeQual = (double *)calloc(n, sizeof(double));
|
||||
pr->quality.NodeQual = (double *)calloc(n, sizeof(double));
|
||||
ERRCODE(MEMCHECK(pr->network.Node));
|
||||
ERRCODE(MEMCHECK(pr->hydraul.NodeDemand));
|
||||
ERRCODE(MEMCHECK(pr->hydraul.NodeHead));
|
||||
@@ -329,8 +328,8 @@ int allocdata(Project *pr)
|
||||
if (!errcode)
|
||||
{
|
||||
n = pr->parser.MaxLinks + 1;
|
||||
pr->network.Link = (Slink *)calloc(n, sizeof(Slink));
|
||||
pr->hydraul.LinkFlow = (double *)calloc(n, sizeof(double));
|
||||
pr->network.Link = (Slink *)calloc(n, sizeof(Slink));
|
||||
pr->hydraul.LinkFlow = (double *)calloc(n, sizeof(double));
|
||||
pr->hydraul.LinkSetting = (double *)calloc(n, sizeof(double));
|
||||
pr->hydraul.LinkStatus = (StatusType *)calloc(n, sizeof(StatusType));
|
||||
ERRCODE(MEMCHECK(pr->network.Link));
|
||||
@@ -339,8 +338,8 @@ int allocdata(Project *pr)
|
||||
ERRCODE(MEMCHECK(pr->hydraul.LinkStatus));
|
||||
}
|
||||
|
||||
// Allocate memory for tanks, sources, pumps, valves,
|
||||
// controls, demands, time patterns, & operating curves
|
||||
// Allocate memory for tanks, sources, pumps, valves, and controls
|
||||
// (memory for Patterns and Curves arrays expanded as each is added)
|
||||
if (!errcode)
|
||||
{
|
||||
pr->network.Tank =
|
||||
@@ -351,35 +350,15 @@ int allocdata(Project *pr)
|
||||
(Svalve *)calloc(pr->parser.MaxValves + 1, sizeof(Svalve));
|
||||
pr->network.Control =
|
||||
(Scontrol *)calloc(pr->parser.MaxControls + 1, sizeof(Scontrol));
|
||||
pr->network.Pattern =
|
||||
(Spattern *)calloc(pr->parser.MaxPats + 1, sizeof(Spattern));
|
||||
pr->network.Curve =
|
||||
(Scurve *)calloc(pr->parser.MaxCurves + 1, sizeof(Scurve));
|
||||
ERRCODE(MEMCHECK(pr->network.Tank));
|
||||
ERRCODE(MEMCHECK(pr->network.Pump));
|
||||
ERRCODE(MEMCHECK(pr->network.Valve));
|
||||
ERRCODE(MEMCHECK(pr->network.Control));
|
||||
ERRCODE(MEMCHECK(pr->network.Pattern));
|
||||
ERRCODE(MEMCHECK(pr->network.Curve));
|
||||
}
|
||||
|
||||
// Initialize pointers used in patterns, curves, and demand category lists
|
||||
// Initialize pointers used in nodes and links
|
||||
if (!errcode)
|
||||
{
|
||||
for (n = 0; n <= pr->parser.MaxPats; n++)
|
||||
{
|
||||
pr->network.Pattern[n].Length = 0;
|
||||
pr->network.Pattern[n].F = NULL;
|
||||
pr->network.Pattern[n].Comment = NULL;
|
||||
}
|
||||
for (n = 0; n <= pr->parser.MaxCurves; n++)
|
||||
{
|
||||
pr->network.Curve[n].Npts = 0;
|
||||
pr->network.Curve[n].Type = GENERIC_CURVE;
|
||||
pr->network.Curve[n].X = NULL;
|
||||
pr->network.Curve[n].Y = NULL;
|
||||
pr->network.Curve[n].Comment = NULL;
|
||||
}
|
||||
for (n = 0; n <= pr->parser.MaxNodes; n++)
|
||||
{
|
||||
pr->network.Node[n].D = NULL; // node demand
|
||||
@@ -397,43 +376,6 @@ int allocdata(Project *pr)
|
||||
return errcode;
|
||||
}
|
||||
|
||||
void freeTmplist(STmplist *t)
|
||||
/*----------------------------------------------------------------
|
||||
** Input: t = pointer to start of a temporary list
|
||||
** Output: none
|
||||
** Purpose: frees memory used for temporary storage
|
||||
** of pattern & curve data
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
STmplist *tnext;
|
||||
while (t != NULL)
|
||||
{
|
||||
tnext = t->next;
|
||||
freeFloatlist(t->x);
|
||||
freeFloatlist(t->y);
|
||||
free(t);
|
||||
t = tnext;
|
||||
}
|
||||
}
|
||||
|
||||
void freeFloatlist(SFloatlist *f)
|
||||
/*----------------------------------------------------------------
|
||||
** Input: f = pointer to start of list of floats
|
||||
** Output: none
|
||||
** Purpose: frees memory used for storing list of floats
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
SFloatlist *fnext;
|
||||
while (f != NULL)
|
||||
{
|
||||
fnext = f->next;
|
||||
free(f);
|
||||
f = fnext;
|
||||
}
|
||||
}
|
||||
|
||||
void freedata(Project *pr)
|
||||
/*----------------------------------------------------------------
|
||||
** Input: none
|
||||
@@ -444,7 +386,6 @@ void freedata(Project *pr)
|
||||
{
|
||||
int j;
|
||||
Pdemand demand, nextdemand;
|
||||
Psource source;
|
||||
|
||||
// Free memory for computed results
|
||||
free(pr->hydraul.NodeDemand);
|
||||
@@ -472,8 +413,7 @@ void freedata(Project *pr)
|
||||
demand = nextdemand;
|
||||
}
|
||||
// Free memory used for WQ source data
|
||||
source = pr->network.Node[j].S;
|
||||
free(source);
|
||||
free(pr->network.Node[j].S);
|
||||
free(pr->network.Node[j].Comment);
|
||||
}
|
||||
free(pr->network.Node);
|
||||
@@ -509,7 +449,8 @@ void freedata(Project *pr)
|
||||
// Free memory for curves
|
||||
if (pr->network.Curve != NULL)
|
||||
{
|
||||
for (j = 0; j <= pr->parser.MaxCurves; j++)
|
||||
// There is no Curve[0]
|
||||
for (j = 1; j <= pr->parser.MaxCurves; j++)
|
||||
{
|
||||
free(pr->network.Curve[j].X);
|
||||
free(pr->network.Curve[j].Y);
|
||||
@@ -807,6 +748,40 @@ int findvalve(Network *network, int index)
|
||||
return NOTFOUND;
|
||||
}
|
||||
|
||||
int findpattern(Network *network, char *id)
|
||||
/*----------------------------------------------------------------
|
||||
** Input: id = time pattern ID
|
||||
** Output: none
|
||||
** Returns: time pattern index, or 0 if pattern not found
|
||||
** Purpose: finds index of time pattern given its ID
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i <= network->Npats; i++)
|
||||
{
|
||||
if (strcmp(id, network->Pattern[i].ID) == 0) return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int findcurve(Network *network, char *id)
|
||||
/*----------------------------------------------------------------
|
||||
** Input: id = data curve ID
|
||||
** Output: none
|
||||
** Returns: data curve index, or 0 if curve not found
|
||||
** Purpose: finds index of data curve given its ID
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i <= network->Ncurves; i++)
|
||||
{
|
||||
if (strcmp(id, network->Curve[i].ID) == 0) return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void adjustpattern(int *pat, int index)
|
||||
/*----------------------------------------------------------------
|
||||
** Local function that modifies a reference to a deleted time pattern
|
||||
@@ -902,6 +877,35 @@ void adjustcurves(Network *network, int index)
|
||||
}
|
||||
}
|
||||
|
||||
int resizecurve(Scurve *curve, int size)
|
||||
/*----------------------------------------------------------------
|
||||
** Input: curve = a data curve object
|
||||
** size = desired number of curve data points
|
||||
** Output: error code
|
||||
** Purpose: resizes a data curve to a desired size
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
double *x;
|
||||
double *y;
|
||||
|
||||
if (curve->Capacity < size)
|
||||
{
|
||||
x = (double *)realloc(curve->X, size * sizeof(double));
|
||||
if (x == NULL) return 101;
|
||||
y = (double *)realloc(curve->Y, size * sizeof(double));
|
||||
if (y == NULL)
|
||||
{
|
||||
free(x);
|
||||
return 101;
|
||||
}
|
||||
curve->X = x;
|
||||
curve->Y = y;
|
||||
curve->Capacity = size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getcomment(Network *network, int object, int index, char *comment)
|
||||
//----------------------------------------------------------------
|
||||
// Input: object = a type of network object
|
||||
@@ -1027,7 +1031,7 @@ char *xstrcpy(char **s1, const char *s2, const size_t n)
|
||||
{
|
||||
size_t n1 = 0, n2;
|
||||
|
||||
// Source string is empty -- free destination string
|
||||
// Source string is empty -- free destination string
|
||||
if (s2 == NULL || strlen(s2) == 0)
|
||||
{
|
||||
free(*s1);
|
||||
|
||||
@@ -11,13 +11,16 @@ Last Updated: 11/27/2018
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "mempool.h"
|
||||
@@ -60,7 +63,7 @@ int openqual(Project *pr)
|
||||
|
||||
int errcode = 0;
|
||||
int n;
|
||||
|
||||
|
||||
// Return if no quality analysis requested
|
||||
if (qual->Qualflag == NONE) return errcode;
|
||||
|
||||
|
||||
@@ -11,6 +11,13 @@ Last Updated: 11/27/2018
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "types.h"
|
||||
@@ -25,6 +32,7 @@ double mixtank(Project *, int, double, double ,double);
|
||||
|
||||
// Imported functions
|
||||
extern void addseg(Project *, int, double, double);
|
||||
extern void reversesegs(Project *, int);
|
||||
|
||||
// Local functions
|
||||
static double piperate(Project *, int);
|
||||
@@ -163,7 +171,7 @@ void reactpipes(Project *pr, long dt)
|
||||
}
|
||||
|
||||
|
||||
void reacttanks(Project *pr, long dt)
|
||||
void reacttanks(Project *pr, long dt)
|
||||
/*
|
||||
**--------------------------------------------------------------
|
||||
** Input: dt = time step
|
||||
@@ -532,7 +540,7 @@ void tankmix2(Project *pr, int i, double vin, double win, double vnet)
|
||||
vt = MAX(0.0, (mixzone->v + vnet - vmz));
|
||||
if (vin > 0.0)
|
||||
{
|
||||
mixzone->c = ((stagzone->c) * (stagzone->v) + win) /
|
||||
mixzone->c = ((mixzone->c) * (mixzone->v) + win) /
|
||||
(mixzone->v + vin);
|
||||
}
|
||||
if (vt > 0.0)
|
||||
@@ -676,18 +684,14 @@ void tankmix4(Project *pr, int i, double vin, double win, double vnet)
|
||||
seg = qual->LastSeg[k];
|
||||
if (vnet > 0.0)
|
||||
{
|
||||
// ... quality is the same, so just add flow volume to last seg
|
||||
// ... inflow quality is same as last segment's quality,
|
||||
// so just add inflow volume to last segment
|
||||
if (fabs(seg->c - cin) < qual->Ctol) seg->v += vnet;
|
||||
|
||||
// ... otherwise add a new last seg to tank which points to old last seg
|
||||
else
|
||||
{
|
||||
qual->LastSeg[k] = NULL;
|
||||
addseg(pr, k, vnet, cin);
|
||||
qual->LastSeg[k]->prev = seg;
|
||||
}
|
||||
// ... otherwise add a new last segment with inflow quality
|
||||
else addseg(pr, k, vnet, cin);
|
||||
|
||||
// ... update reported tank quality
|
||||
// Update reported tank quality
|
||||
tank->C = qual->LastSeg[k]->c;
|
||||
}
|
||||
|
||||
@@ -697,28 +701,48 @@ void tankmix4(Project *pr, int i, double vin, double win, double vnet)
|
||||
vsum = 0.0;
|
||||
wsum = 0.0;
|
||||
vnet = -vnet;
|
||||
|
||||
// Reverse segment chain so segments are processed from last to first
|
||||
reversesegs(pr, k);
|
||||
|
||||
// While there is still volume to remove
|
||||
while (vnet > 0.0)
|
||||
{
|
||||
seg = qual->LastSeg[k];
|
||||
// ... start with reversed first segment
|
||||
seg = qual->FirstSeg[k];
|
||||
if (seg == NULL) break;
|
||||
|
||||
// ... find volume to remove from it
|
||||
vseg = seg->v;
|
||||
vseg = MIN(vseg, vnet);
|
||||
if (seg == qual->FirstSeg[k]) vseg = vnet;
|
||||
if (seg == qual->LastSeg[k]) vseg = vnet;
|
||||
|
||||
// ... update total volume & mass removed
|
||||
vsum += vseg;
|
||||
wsum += (seg->c) * vseg;
|
||||
|
||||
// ... update remiaing volume to remove
|
||||
vnet -= vseg;
|
||||
if (vnet >= 0.0 && vseg >= seg->v) // Seg used up
|
||||
|
||||
// ... if no more volume left in current segment
|
||||
if (vnet >= 0.0 && vseg >= seg->v)
|
||||
{
|
||||
// ... replace current segment with previous one
|
||||
if (seg->prev)
|
||||
{
|
||||
qual->LastSeg[k] = seg->prev;
|
||||
qual->FirstSeg[k] = seg->prev;
|
||||
seg->prev = qual->FreeSeg;
|
||||
qual->FreeSeg = seg;
|
||||
}
|
||||
}
|
||||
else seg->v -= vseg; // Remaining volume in segment
|
||||
|
||||
// ... otherwise reduce volume of current segment
|
||||
else seg->v -= vseg;
|
||||
}
|
||||
|
||||
// Restore original orientation of segment chain
|
||||
reversesegs(pr, k);
|
||||
|
||||
// Reported tank quality is mixture of flow released and any inflow
|
||||
tank->C = (wsum + win) / (vsum + vin);
|
||||
}
|
||||
|
||||
@@ -11,13 +11,17 @@ Last Updated: 11/27/2018
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "mempool.h"
|
||||
#include "types.h"
|
||||
|
||||
|
||||
16
src/report.c
16
src/report.c
@@ -11,13 +11,15 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define snprintf _snprintf
|
||||
@@ -83,7 +85,7 @@ int copyreport(Project* pr, char *filename)
|
||||
FILE *tfile;
|
||||
int c;
|
||||
Report *rpt = &pr->report;
|
||||
|
||||
|
||||
// Check that project's report file exists
|
||||
if (rpt->RptFile == NULL) return 0;
|
||||
|
||||
@@ -101,7 +103,7 @@ int copyreport(Project* pr, char *filename)
|
||||
while ((c = fgetc(rpt->RptFile)) != EOF) fputc(c, tfile);
|
||||
fclose(rpt->RptFile);
|
||||
}
|
||||
|
||||
|
||||
// Close destination file
|
||||
fclose(tfile);
|
||||
|
||||
|
||||
12
src/rules.c
12
src/rules.c
@@ -11,13 +11,15 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "types.h"
|
||||
#include "funcs.h"
|
||||
|
||||
@@ -18,13 +18,16 @@
|
||||
linsolve() -- called from netsolve() in HYDRAUL.C
|
||||
*/
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
32
src/types.h
32
src/types.h
@@ -7,7 +7,7 @@
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 03/17/2019
|
||||
Last Updated: 04/03/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
@@ -317,23 +317,6 @@ struct IDstring // Holds component ID label
|
||||
char ID[MAXID+1];
|
||||
};
|
||||
|
||||
struct Floatlist // Element of List of Numbers
|
||||
{
|
||||
double value; // element's numerical value
|
||||
struct Floatlist *next; // next element on the list
|
||||
};
|
||||
typedef struct Floatlist SFloatlist;
|
||||
|
||||
struct Tmplist // Item of Temporary List of Objects
|
||||
{
|
||||
int i; // object's index
|
||||
char ID[MAXID+1]; // object's ID name
|
||||
SFloatlist *x; // list of data values
|
||||
SFloatlist *y; // list of data values
|
||||
struct Tmplist *next; // next object on list
|
||||
};
|
||||
typedef struct Tmplist STmplist; // Pointer to temporary list of objects
|
||||
|
||||
typedef struct // Time Pattern Object
|
||||
{
|
||||
char ID[MAXID+1]; // pattern ID
|
||||
@@ -348,6 +331,7 @@ typedef struct // Curve Object
|
||||
char *Comment; // curve comment
|
||||
CurveType Type; // curve type
|
||||
int Npts; // number of points
|
||||
int Capacity; // size of X & Y arrays
|
||||
double *X; // x-values
|
||||
double *Y; // y-values
|
||||
} Scurve;
|
||||
@@ -573,14 +557,11 @@ typedef struct {
|
||||
ErrTok, // Index of error-producing token
|
||||
Unitsflag, // Unit system flag
|
||||
Flowflag, // Flow units flag
|
||||
Pressflag; // Pressure units flag
|
||||
Pressflag, // Pressure units flag
|
||||
DefPat; // Default demand pattern
|
||||
|
||||
STmplist
|
||||
*Patlist, // Temporary time pattern list
|
||||
*PrevPat, // Previous pattern list element
|
||||
*Curvelist, // Temporary list of curves
|
||||
*PrevCurve; // Previous curve list element
|
||||
|
||||
Spattern *PrevPat; // Previous pattern processed
|
||||
Scurve *PrevCurve; // Previous curve processed
|
||||
double *X; // Temporary array for curve data
|
||||
|
||||
} Parser;
|
||||
@@ -738,7 +719,6 @@ typedef struct {
|
||||
*Xflow; // Inflow - outflow at each node
|
||||
|
||||
int
|
||||
DefPat, // Default demand pattern
|
||||
Epat, // Energy cost time pattern
|
||||
DemandModel, // Fixed or pressure dependent
|
||||
Formflag, // Head loss formula flag
|
||||
|
||||
48
src/util/cstr_helper.c
Normal file
48
src/util/cstr_helper.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Module: util/cstr_helper.c
|
||||
Description: Provides C string helper functions
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 04/02/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cstr_helper.h"
|
||||
|
||||
|
||||
int copy_cstr(const char *source, char **dest)
|
||||
// Determines length, allocates memory, and returns a null terminated copy
|
||||
// Be Aware: caller is responsible for freeing memory
|
||||
{
|
||||
size_t size;
|
||||
|
||||
size = 1 + strlen(source);
|
||||
*dest = (char *) calloc(size, sizeof(char));
|
||||
|
||||
if (*dest == NULL)
|
||||
return -1;
|
||||
else {
|
||||
#ifdef _MSC_VER
|
||||
strncpy_s(*dest, size, source, size);
|
||||
#else
|
||||
strncpy(*dest, source, size);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool isnullterm_cstr(const char *source)
|
||||
{
|
||||
if (strchr(source, '\0'))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
25
src/util/cstr_helper.h
Normal file
25
src/util/cstr_helper.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Module: util/cstr_helper.h
|
||||
Description: Provides C string helper functions
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 04/02/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef CSTR_HELPER_H_
|
||||
#define CSTR_HELPER_H_
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
int copy_cstr(const char *source, char **destination);
|
||||
bool isnullterm_cstr(const char *source);
|
||||
|
||||
|
||||
#endif /* CSTR_HELPER_H_ */
|
||||
@@ -1,14 +1,15 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// errormanager.c
|
||||
//
|
||||
// Purpose: Provides a simple interface for managing runtime error messages.
|
||||
//
|
||||
// Date: 08/25/2017
|
||||
//
|
||||
// Author: Michael E. Tryby
|
||||
// US EPA - ORD/NRMRL
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
******************************************************************************
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Module: util/errormanager.c
|
||||
Description: Provides a simple interface for managing errors
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 04/02/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
//#ifdef _WIN32
|
||||
//#define _CRTDBG_MAP_ALLOC
|
||||
@@ -22,6 +23,12 @@
|
||||
#include "errormanager.h"
|
||||
|
||||
|
||||
typedef struct error_s {
|
||||
int error_status;
|
||||
void (*p_msg_lookup)(int, char*, int);
|
||||
} error_handle_t;
|
||||
|
||||
|
||||
error_handle_t *create_error_manager(void (*p_error_message)(int, char*, int))
|
||||
//
|
||||
// Purpose: Constructs a new error handle.
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
/*
|
||||
* errormanager.h
|
||||
*
|
||||
* Created on: Aug 25, 2017
|
||||
*
|
||||
* Author: Michael E. Tryby
|
||||
* US EPA - ORD/NRMRL
|
||||
*/
|
||||
******************************************************************************
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Module: util/errormanager.h
|
||||
Description: Provides a simple interface for managing errors
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 04/02/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ERRORMANAGER_H_
|
||||
#define ERRORMANAGER_H_
|
||||
@@ -17,11 +21,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct error_s {
|
||||
int error_status;
|
||||
void (*p_msg_lookup)(int, char*, int);
|
||||
} error_handle_t;
|
||||
// Forward declaration
|
||||
typedef struct error_s error_handle_t;
|
||||
|
||||
error_handle_t* create_error_manager(void (*p_error_message)(int, char*, int));
|
||||
void delete_error_manager(error_handle_t* error_handle);
|
||||
|
||||
211
src/util/filemanager.c
Normal file
211
src/util/filemanager.c
Normal file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Module: util/filemanager.c
|
||||
Description: Provides a simple interface for managing files
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 04/01/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
// MSVC ONLY
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "filemanager.h"
|
||||
|
||||
|
||||
typedef struct file_s {
|
||||
char *filename; // Assumes this is a null terminated string
|
||||
FILE *file;
|
||||
} file_handle_t;
|
||||
|
||||
|
||||
// local (private) functions
|
||||
int _fopen(FILE **f, const char *name, const char *mode);
|
||||
int _get_temp_filename(char **tempname);
|
||||
|
||||
|
||||
file_handle_t *create_file_manager() {
|
||||
|
||||
file_handle_t *file_handle;
|
||||
file_handle = (file_handle_t *)calloc(1, sizeof(file_handle_t));
|
||||
|
||||
file_handle->filename = NULL;
|
||||
file_handle->file = NULL;
|
||||
|
||||
return file_handle;
|
||||
}
|
||||
|
||||
void delete_file_manager(file_handle_t *file_handle) {
|
||||
|
||||
if (file_handle->file != NULL)
|
||||
close_file(file_handle);
|
||||
|
||||
free(file_handle->filename);
|
||||
free(file_handle);
|
||||
}
|
||||
|
||||
|
||||
int get_filename(file_handle_t *file_handle, char **filename)
|
||||
//
|
||||
// BE AWARE: The memory allocated here must be freed by the caller
|
||||
//
|
||||
{
|
||||
return copy_cstr(file_handle->filename, filename);
|
||||
}
|
||||
|
||||
|
||||
int open_file(file_handle_t *file_handle, const char *filename, const char *file_mode) {
|
||||
int error = 0;
|
||||
|
||||
if (filename == NULL)
|
||||
_get_temp_filename(&(file_handle->filename));
|
||||
else
|
||||
copy_cstr(filename, &(file_handle->filename));
|
||||
|
||||
if (file_mode == NULL)
|
||||
error = -1;
|
||||
else {
|
||||
error = _fopen(&(file_handle->file), file_handle->filename, file_mode);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int seek_file(file_handle_t *file_handle, F_OFF offset, int whence)
|
||||
{
|
||||
#ifdef _MSC_VER // Windows (32-bit and 64-bit)
|
||||
#define FSEEK64 _fseeki64
|
||||
#else // Other platforms
|
||||
#define FSEEK64 fseeko
|
||||
#endif
|
||||
|
||||
return FSEEK64(file_handle->file, offset, whence);
|
||||
}
|
||||
|
||||
F_OFF tell_file(file_handle_t *file_handle)
|
||||
{
|
||||
#ifdef _MSC_VER // Windows (32-bit and 64-bit)
|
||||
#define FTELL64 _ftelli64
|
||||
#else // Other platforms
|
||||
#define FTELL64 ftello
|
||||
#endif
|
||||
|
||||
return FTELL64(file_handle->file);
|
||||
}
|
||||
|
||||
// Read and write to a binary file
|
||||
size_t read_file(void *ptr, size_t size, size_t nmemb, file_handle_t *file_handle)
|
||||
{
|
||||
return fread(ptr, size, nmemb, file_handle->file);
|
||||
}
|
||||
|
||||
size_t write_file(const void * ptr, size_t size, size_t count, file_handle_t *file_handle)
|
||||
{
|
||||
return fwrite(ptr, size, count, file_handle->file);
|
||||
}
|
||||
|
||||
|
||||
// print and get from a text file
|
||||
int printf_file(file_handle_t *file_handle, const char *format, ... )
|
||||
{
|
||||
int error = 0;
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
error = vfprintf(file_handle->file, format, args);
|
||||
va_end(args);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int gets_file(char *str, int num, file_handle_t *file_handle)
|
||||
{
|
||||
fgets(str, num, file_handle->file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int close_file(file_handle_t *file_handle) {
|
||||
int error = 0;
|
||||
|
||||
if (file_handle->file != NULL) {
|
||||
error = fclose(file_handle->file);
|
||||
file_handle->file = NULL;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
int remove_file(file_handle_t *file_handle) {
|
||||
return remove(file_handle->filename);
|
||||
}
|
||||
|
||||
|
||||
bool is_valid(file_handle_t *file_handle)
|
||||
{
|
||||
if ((file_handle->filename == NULL && file_handle->file == NULL) ||
|
||||
(isnullterm_cstr(file_handle->filename) && file_handle != NULL))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int _fopen(FILE **f, const char *name, const char *mode)
|
||||
//
|
||||
// Purpose: Substitute for fopen_s on platforms where it doesn't exist
|
||||
// Note: fopen_s is part of C++11 standard
|
||||
//
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
ret = (int)fopen_s(f, name, mode);
|
||||
#else
|
||||
*f = fopen(name, mode);
|
||||
if (!*f)
|
||||
ret = -1;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _get_temp_filename(char **tempname)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
char *name = NULL;
|
||||
|
||||
// --- use Windows _tempnam function to get a pointer to an
|
||||
// unused file name that begins with "en"
|
||||
if ((name = _tempnam(name, "en")) == NULL) {
|
||||
error = -1;
|
||||
return error;
|
||||
}
|
||||
else
|
||||
copy_cstr(name, tempname);
|
||||
|
||||
// --- free the pointer returned by _tempnam
|
||||
if (name)
|
||||
free(name);
|
||||
|
||||
// --- for non-Windows systems:
|
||||
#else
|
||||
// --- use system function mkstemp() to create a temporary file name
|
||||
copy_cstr("enXXXXXX", tempname);
|
||||
error = mkstemp(*tempname);
|
||||
#endif
|
||||
return error;
|
||||
}
|
||||
81
src/util/filemanager.h
Normal file
81
src/util/filemanager.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Module: util/filemanager.h
|
||||
Description: Provides a simple interface for managing files
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 04/01/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef FILEMANAGER_H_
|
||||
#define FILEMANAGER_H_
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "cstr_helper.h"
|
||||
|
||||
|
||||
// F_OFF Must be a 8 byte / 64 bit integer for large file support
|
||||
#ifdef _MSC_VER // Windows (32-bit and 64-bit)
|
||||
#define F_OFF __int64
|
||||
#else // Other platforms
|
||||
#define F_OFF off_t
|
||||
#endif
|
||||
|
||||
#define FILE_MAXNAME 259
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Forward declariation of file_handle_t
|
||||
typedef struct file_s file_handle_t;
|
||||
|
||||
|
||||
file_handle_t *create_file_manager();
|
||||
|
||||
void delete_file_manager(file_handle_t *file_handle);
|
||||
|
||||
|
||||
int get_filename(file_handle_t *file_handle, char **filename);
|
||||
|
||||
|
||||
int open_file(file_handle_t *file_handle, const char *filename, const char *file_mode);
|
||||
|
||||
int seek_file(file_handle_t *file_handle, F_OFF offset, int whence);
|
||||
|
||||
F_OFF tell_file(file_handle_t *file_handle);
|
||||
|
||||
|
||||
// Functions for working with binary files
|
||||
size_t read_file(void *ptr, size_t size, size_t nmemb, file_handle_t *file_handle);
|
||||
|
||||
size_t write_file(const void *ptr, size_t size, size_t count, file_handle_t *file_handle);
|
||||
|
||||
|
||||
// Functions for working with text files
|
||||
int printf_file(file_handle_t *file_handle, const char *format, ... );
|
||||
|
||||
int gets_file(char *str, int num, file_handle_t *file_handle);
|
||||
|
||||
|
||||
int close_file(file_handle_t *file_handle);
|
||||
|
||||
int remove_file(file_handle_t *file_handle);
|
||||
|
||||
|
||||
bool is_valid(file_handle_t *file_handle);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FILEMANAGER_H_ */
|
||||
@@ -30,7 +30,8 @@ set(toolkit_test_srcs
|
||||
test_pattern.cpp
|
||||
test_curve.cpp
|
||||
test_control.cpp
|
||||
test_net_builder.cpp)
|
||||
test_net_builder.cpp
|
||||
)
|
||||
|
||||
add_executable(test_toolkit ${toolkit_test_srcs})
|
||||
|
||||
@@ -59,6 +60,10 @@ add_test(NAME test_reent
|
||||
add_test(NAME test_errormanager
|
||||
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_errormanager)
|
||||
|
||||
add_test(NAME test_filemanager
|
||||
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_filemanager
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/outfile/data)
|
||||
|
||||
add_test(NAME test_output
|
||||
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_output
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/outfile/data)
|
||||
|
||||
@@ -22,10 +22,12 @@ BOOST_AUTO_TEST_SUITE (test_analysis)
|
||||
BOOST_FIXTURE_TEST_CASE(test_anlys_getoption, FixtureOpenClose)
|
||||
{
|
||||
int i;
|
||||
double array[13];
|
||||
|
||||
std::vector<double> test;
|
||||
std::vector<double> ref = {40.0, 0.001, 0.01, 0.5, 1.0, 0.0, 0.0, 1.0, 0.0, 75.0, 0.0, 0.0, 0.0};
|
||||
std::vector<double> test(23);
|
||||
double *array = test.data();
|
||||
|
||||
std::vector<double> ref = {40.0, 0.001, 0.01, 0.5, 1.0, 0.0, 0.0, 0.0, 75.0, 0.0, 0.0, 0.0,
|
||||
1.0, 1.0, 10.0, 2.0, 10.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0};
|
||||
|
||||
error = EN_solveH(ph);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
@@ -34,24 +36,25 @@ BOOST_FIXTURE_TEST_CASE(test_anlys_getoption, FixtureOpenClose)
|
||||
BOOST_REQUIRE(error == 0);
|
||||
|
||||
|
||||
for (i=EN_TRIALS; i<=EN_DEMANDCHARGE; i++) {
|
||||
error = EN_getoption(ph, i, &array[i]);
|
||||
for (i=EN_TRIALS; i<=EN_CONCENLIMIT; i++) {
|
||||
error = EN_getoption(ph, i, array++);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
}
|
||||
|
||||
test.assign(array, array + 13);
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(ref.begin(), ref.end(), test.begin(), test.end());
|
||||
|
||||
error = EN_getoption(ph, 18, &array[0]);
|
||||
double temp;
|
||||
error = EN_getoption(ph, 25, &temp);
|
||||
BOOST_CHECK(error == 251);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_anlys_gettimeparam, FixtureOpenClose)
|
||||
{
|
||||
int i;
|
||||
long array[16];
|
||||
|
||||
std::vector<long> test;
|
||||
std::vector<long> test(16);
|
||||
long *array = test.data();
|
||||
|
||||
std::vector<long> ref = {86400, 3600, 300, 7200, 0, 3600, 0, 360, 0, 25, 0, 86400, 86400, 0, 3600, 0};
|
||||
|
||||
error = EN_solveH(ph);
|
||||
@@ -62,14 +65,15 @@ BOOST_FIXTURE_TEST_CASE(test_anlys_gettimeparam, FixtureOpenClose)
|
||||
|
||||
|
||||
for (i=EN_DURATION; i<=EN_NEXTEVENTTANK; i++) {
|
||||
error = EN_gettimeparam(ph, i, &array[i]);
|
||||
error = EN_gettimeparam(ph, i, array++);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
}
|
||||
|
||||
test.assign(array, array + 16);
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(ref.begin(), ref.end(), test.begin(), test.end());
|
||||
|
||||
error = EN_gettimeparam(ph, 18, &array[0]);
|
||||
long temp;
|
||||
error = EN_gettimeparam(ph, 18, &temp);
|
||||
BOOST_CHECK(error == 251);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
@@ -35,6 +35,35 @@ BOOST_FIXTURE_TEST_CASE(test_curve_comments, FixtureOpenClose)
|
||||
error = EN_getcomment(ph, EN_CURVE, index, comment);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_CHECK(check_string(comment, (char *)"Curve 1"));
|
||||
|
||||
// Test of EN_setcurve and EN_getcurve
|
||||
int i;
|
||||
char id1[] = "NewCurve";
|
||||
int n1 = 5;
|
||||
double X1[] = {16.88889, 19.5, 22.13889, 25.94445, 33.33334};
|
||||
double Y1[] = {156.7, 146.5, 136.2, 117.9, 50.0};
|
||||
int n2;
|
||||
double X2[5], Y2[5];
|
||||
char id2[EN_MAXID+1];
|
||||
|
||||
// Add data to a new curve
|
||||
error = EN_addcurve(ph, id1);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_getcurveindex(ph, id1, &i);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_setcurve(ph, i, X1, Y1, n1);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
|
||||
// Retrieve data from curve
|
||||
error = EN_getcurve(ph, i, id2, &n2, X2, Y2);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_CHECK(check_string(id2, id1));
|
||||
BOOST_REQUIRE(n2 == n1);
|
||||
for (i = 0; i < n1; i++)
|
||||
{
|
||||
BOOST_CHECK(X1[i] == X2[i]);
|
||||
BOOST_CHECK(Y1[i] == Y2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "test_toolkit.hpp"
|
||||
|
||||
@@ -11,6 +11,14 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "test_toolkit.hpp"
|
||||
@@ -35,6 +43,9 @@ BOOST_AUTO_TEST_CASE(test_init_close)
|
||||
|
||||
struct FixtureInitClose {
|
||||
FixtureInitClose() {
|
||||
error = 0;
|
||||
ph = NULL;
|
||||
|
||||
EN_createproject(&ph);
|
||||
EN_init(ph, DATA_PATH_RPT, DATA_PATH_OUT, EN_GPM, EN_HW);
|
||||
}
|
||||
@@ -50,55 +61,55 @@ struct FixtureInitClose {
|
||||
|
||||
|
||||
|
||||
//BOOST_AUTO_TEST_CASE(net_builder_I)
|
||||
//{
|
||||
// int error = 0;
|
||||
// int flag = 00;
|
||||
// long t, tstep;
|
||||
// int i, ind, Lindex, Nindex, Cindex;
|
||||
// double h_orig, h_build, h_build_loaded;
|
||||
// BOOST_AUTO_TEST_CASE(net_builder_I)
|
||||
// {
|
||||
// int error = 0;
|
||||
// int flag = 00;
|
||||
// long t, tstep;
|
||||
// int i, ind, Lindex, Nindex, Cindex;
|
||||
// double h_orig, h_build, h_build_loaded;
|
||||
//
|
||||
// // first we load Net1.inp, run it and record the head in Tank 2 at the end of the simulation (h_orig)
|
||||
// EN_Project ph = NULL;
|
||||
// EN_createproject(&ph);
|
||||
// // first we load Net1.inp, run it and record the head in Tank 2 at the end of the simulation (h_orig)
|
||||
// EN_Project ph = NULL;
|
||||
// EN_createproject(&ph);
|
||||
//
|
||||
// std::string path_inp = std::string(DATA_PATH_NET1);
|
||||
// std::string path_rpt = std::string(DATA_PATH_RPT);
|
||||
// std::string path_out = std::string(DATA_PATH_OUT);
|
||||
// std::string path_inp = std::string(DATA_PATH_NET1);
|
||||
// std::string path_rpt = std::string(DATA_PATH_RPT);
|
||||
// std::string path_out = std::string(DATA_PATH_OUT);
|
||||
//
|
||||
// error = EN_open(ph, path_inp.c_str(), path_rpt.c_str(), path_out.c_str());
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
// error = EN_open(ph, path_inp.c_str(), path_rpt.c_str(), path_out.c_str());
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
//
|
||||
// error = EN_getnodeindex(ph, (char *)"2", &Nindex);
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
// error = EN_getnodeindex(ph, (char *)"2", &Nindex);
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
//
|
||||
// error = EN_openH(ph);
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
// error = EN_openH(ph);
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
//
|
||||
// error = EN_initH(ph, flag);
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
// error = EN_initH(ph, flag);
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
//
|
||||
// do {
|
||||
// error = EN_runH(ph, &t);
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
// do {
|
||||
// error = EN_runH(ph, &t);
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
//
|
||||
// // this is the head at the end of the simulation after loading the original Net1.inp
|
||||
// error = EN_getnodevalue(ph, Nindex, EN_HEAD, &h_orig);
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
// // this is the head at the end of the simulation after loading the original Net1.inp
|
||||
// error = EN_getnodevalue(ph, Nindex, EN_HEAD, &h_orig);
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
//
|
||||
// error = EN_nextH(ph, &tstep);
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
// error = EN_nextH(ph, &tstep);
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
//
|
||||
// } while (tstep > 0);
|
||||
// } while (tstep > 0);
|
||||
//
|
||||
// error = EN_closeH(ph);
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
// error = EN_closeH(ph);
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
//
|
||||
// error = EN_close(ph);
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
// error = EN_close(ph);
|
||||
// BOOST_REQUIRE(error == 0);
|
||||
//
|
||||
// EN_deleteproject(&ph);
|
||||
//}
|
||||
// EN_deleteproject(&ph);
|
||||
// }
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_build_net1, FixtureInitClose)
|
||||
{
|
||||
@@ -121,8 +132,8 @@ BOOST_FIXTURE_TEST_CASE(test_build_net1, FixtureInitClose)
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_setpattern(ph, 1, P, 12);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_setoption(ph, EN_DEFDEMANDPAT, 1);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
//error = EN_setoption(ph, EN_DEFDEMANDPAT, 1);
|
||||
//BOOST_REQUIRE(error == 0);
|
||||
for (i = 0; i < 9; i++)
|
||||
{
|
||||
error = EN_addnode(ph, juncs[i], EN_JUNCTION);
|
||||
@@ -131,6 +142,8 @@ BOOST_FIXTURE_TEST_CASE(test_build_net1, FixtureInitClose)
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_setnodevalue(ph, i + 1, EN_BASEDEMAND, d[i]);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_setnodevalue(ph, i+1, EN_PATTERN, 1);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
error = EN_setcoord(ph, i + 1, X[i], Y[i]);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
//error = EN_setdemandpattern(ph, i + 1, 1, 1);
|
||||
|
||||
@@ -33,12 +33,9 @@ BOOST_AUTO_TEST_CASE(add_set_pattern)
|
||||
error = EN_open(ph, path_inp.c_str(), path_rpt.c_str(), "");
|
||||
BOOST_REQUIRE(error == 0);
|
||||
|
||||
// Get the default pattern index
|
||||
double dblPatIdx;
|
||||
int defPatIdx;
|
||||
// Assign the default pattern index
|
||||
int defPatIdx = 1;
|
||||
int patIdx;
|
||||
EN_getoption(ph, EN_DEFDEMANDPAT, &dblPatIdx);
|
||||
defPatIdx = (int)dblPatIdx;
|
||||
|
||||
// Rename the default pattern
|
||||
EN_setpatternid(ph, defPatIdx, (char *)"Pat1");
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
@@ -109,37 +111,39 @@ BOOST_AUTO_TEST_SUITE(test_proj_fixture)
|
||||
BOOST_FIXTURE_TEST_CASE(test_title, FixtureOpenClose)
|
||||
{
|
||||
// How is the API user supposed to know array size?
|
||||
char c_test[3][80], c_ref[3][80];
|
||||
char c_test[3][80];
|
||||
|
||||
strncpy(c_ref[0], " EPANET Example Network 1", 26);
|
||||
strncpy(c_ref[1], "A simple example of modeling chlorine decay. Both bulk and", 59);
|
||||
strncpy(c_ref[2], "wall reactions are included. ", 30);
|
||||
// ref is an automatic variable and therefore doesn't need to be deleted
|
||||
std::string ref[3] = {
|
||||
" EPANET Example Network 1",
|
||||
"A simple example of modeling chlorine decay. Both bulk and",
|
||||
"wall reactions are included. "};
|
||||
|
||||
error = EN_gettitle(ph, c_test[0], c_test[1], c_test[2]);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
std::string test (c_test[i]);
|
||||
std::string ref (c_ref[i]);
|
||||
BOOST_CHECK(check_string(test, ref));
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
std::string test (c_test[i]);
|
||||
BOOST_CHECK(check_string(test, ref[i]));
|
||||
}
|
||||
|
||||
// Need a test for EN_settitle
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_getcount, FixtureOpenClose)
|
||||
{
|
||||
int i, array[7];
|
||||
int i;
|
||||
|
||||
std::vector<int> test;
|
||||
std::vector<int> ref = { 11, 2, 13, 1, 1, 2, 0 };
|
||||
std::vector<int> test(7);
|
||||
int *array = test.data();
|
||||
|
||||
std::vector<int> ref = { 11, 2, 13, 1, 1, 2, 0 };
|
||||
|
||||
for (i=EN_NODECOUNT; i<=EN_RULECOUNT; i++) {
|
||||
error = EN_getcount(ph, i, &array[i]);
|
||||
error = EN_getcount(ph, i, array++);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
}
|
||||
|
||||
test.assign(array, array + 7);
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(ref.begin(), ref.end(), test.begin(), test.end());
|
||||
|
||||
error = EN_getcount(ph, 7, &i);
|
||||
|
||||
@@ -21,9 +21,10 @@ BOOST_AUTO_TEST_SUITE (test_report)
|
||||
BOOST_FIXTURE_TEST_CASE(test_rprt_anlysstats, FixtureOpenClose)
|
||||
{
|
||||
int i;
|
||||
double array[5];
|
||||
|
||||
std::vector<double> test;
|
||||
std::vector<double> test(5);
|
||||
double *array = test.data();
|
||||
|
||||
std::vector<double> ref = {3.0, 7.0799498320679432e-06, 1.6680242187483429e-08,
|
||||
0.0089173150106518495, 0.99999998187144024};
|
||||
|
||||
@@ -35,15 +36,13 @@ BOOST_FIXTURE_TEST_CASE(test_rprt_anlysstats, FixtureOpenClose)
|
||||
|
||||
|
||||
for (i=EN_ITERATIONS; i<=EN_MASSBALANCE; i++) {
|
||||
error = EN_getstatistic(ph, i, &array[i]);
|
||||
error = EN_getstatistic(ph, i, array++);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
}
|
||||
|
||||
test.assign(array, array + 5);
|
||||
// BOOST_CHECK_EQUAL_COLLECTIONS(ref.begin(), ref.end(), test.begin(), test.end());
|
||||
BOOST_CHECK(check_cdd_double(test, ref, 3));
|
||||
|
||||
error = EN_getstatistic(ph, 8, &array[0]);
|
||||
double temp;
|
||||
error = EN_getstatistic(ph, 8, &temp);
|
||||
BOOST_CHECK(error == 251);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#ifndef TEST_TOOLKIT_HPP
|
||||
#define TEST_TOOLKIT_HPP
|
||||
|
||||
|
||||
#include "epanet2_2.h"
|
||||
|
||||
|
||||
@@ -25,6 +24,9 @@
|
||||
|
||||
struct FixtureOpenClose{
|
||||
FixtureOpenClose() {
|
||||
error = 0;
|
||||
ph = NULL;
|
||||
|
||||
EN_createproject(&ph);
|
||||
error = EN_open(ph, DATA_PATH_NET1, DATA_PATH_RPT, DATA_PATH_OUT);
|
||||
}
|
||||
@@ -41,6 +43,9 @@ struct FixtureOpenClose{
|
||||
|
||||
struct FixtureAfterStep{
|
||||
FixtureAfterStep() {
|
||||
error = 0;
|
||||
ph = NULL;
|
||||
|
||||
flag = 0;
|
||||
tstop = 10800;
|
||||
|
||||
|
||||
@@ -7,11 +7,14 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
|
||||
|
||||
set (test_source
|
||||
./test_errormanager.cpp
|
||||
../../src/util/errormanager.c
|
||||
)
|
||||
|
||||
add_executable(test_errormanager ${test_source})
|
||||
add_executable(test_errormanager ./test_errormanager.cpp
|
||||
../../src/util/errormanager.c)
|
||||
target_include_directories(test_errormanager PUBLIC ../../src/)
|
||||
target_link_libraries(test_errormanager ${Boost_LIBRARIES})
|
||||
|
||||
|
||||
add_executable(test_filemanager ./test_filemanager.cpp
|
||||
../../src/util/filemanager.c
|
||||
../../src/util/cstr_helper.c)
|
||||
target_include_directories(test_filemanager PUBLIC ../../src/)
|
||||
target_link_libraries(test_filemanager ${Boost_LIBRARIES})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
|
||||
#define BOOST_TEST_MODULE errormanager
|
||||
//#define BOOST_TEST_DYN_LINK
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "util/errormanager.h"
|
||||
@@ -15,10 +15,10 @@ void mock_lookup(int errcode, char *errmsg, int len)
|
||||
char *msg = NULL;
|
||||
|
||||
if (errcode == 100) {
|
||||
msg = MESSAGE_STRING;
|
||||
msg = (char *)MESSAGE_STRING;
|
||||
}
|
||||
else {
|
||||
msg = "";
|
||||
msg = (char *)"";
|
||||
}
|
||||
strncpy(errmsg, msg, len);
|
||||
}
|
||||
|
||||
97
tests/util/test_filemanager.cpp
Normal file
97
tests/util/test_filemanager.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
Project: OWA EPANET
|
||||
Version: 2.2
|
||||
Module: util/test_filemanager.cpp
|
||||
Description: Tests for util/filemanager.c
|
||||
Authors: see AUTHORS
|
||||
Copyright: see AUTHORS
|
||||
License: see LICENSE
|
||||
Last Updated: 04/01/2019
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE filemanager
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "util/filemanager.h"
|
||||
|
||||
|
||||
#define DATA_PATH_OUTPUT "./example1.out"
|
||||
|
||||
|
||||
boost::test_tools::predicate_result check_string(std::string test, std::string ref)
|
||||
{
|
||||
if (ref.compare(test) == 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(test_filemanager)
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE (test_create_destroy)
|
||||
{
|
||||
file_handle_t *file_handle = NULL;
|
||||
|
||||
file_handle = create_file_manager();
|
||||
BOOST_CHECK(file_handle != NULL);
|
||||
BOOST_CHECK(is_valid(file_handle) == true);
|
||||
|
||||
delete_file_manager(file_handle);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_open_close)
|
||||
{
|
||||
int error = 0;
|
||||
file_handle_t *file_handle = NULL;
|
||||
|
||||
file_handle = create_file_manager();
|
||||
BOOST_CHECK(file_handle != NULL);
|
||||
|
||||
error = open_file(file_handle, DATA_PATH_OUTPUT, "rb");
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_CHECK(is_valid(file_handle) == true);
|
||||
|
||||
error = close_file(file_handle);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
|
||||
delete_file_manager(file_handle);
|
||||
}
|
||||
|
||||
struct Fixture{
|
||||
Fixture() {
|
||||
error = 0;
|
||||
file_handle = NULL;
|
||||
|
||||
file_handle = create_file_manager();
|
||||
open_file(file_handle, NULL, "wt");
|
||||
}
|
||||
~Fixture() {
|
||||
close_file(file_handle);
|
||||
delete_file_manager(file_handle);
|
||||
}
|
||||
int error;
|
||||
file_handle_t *file_handle;
|
||||
};
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_temp_file, Fixture)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
printf_file(file_handle, "%s", "This is a test.");
|
||||
|
||||
error = get_filename(file_handle, &filename);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_CHECK(is_valid(file_handle) == true);
|
||||
|
||||
BOOST_CHECK(boost::filesystem::exists(filename) == true);
|
||||
|
||||
free(filename);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
Reference in New Issue
Block a user