Refactors the API's demand editing functions
This commit is contained in:
@@ -307,6 +307,9 @@ Public Const EN_R_IS_ACTIVE = 3
|
|||||||
'Nodal Demand Functions
|
'Nodal Demand Functions
|
||||||
Declare Function ENgetdemandmodel Lib "epanet2.dll" (type_ As Long, pmin As Single, preq As Single, pexp As Single) As Long
|
Declare Function ENgetdemandmodel Lib "epanet2.dll" (type_ As Long, pmin As Single, preq As Single, pexp As Single) As Long
|
||||||
Declare Function ENsetdemandmodel Lib "epanet2.dll" (ByVal type_ As Long, ByVal pmin As Single, ByVal preq As Single, ByVal pexp As Single) As Long
|
Declare Function ENsetdemandmodel Lib "epanet2.dll" (ByVal type_ As Long, ByVal pmin As Single, ByVal preq As Single, ByVal pexp As Single) As Long
|
||||||
|
Declare Function ENadddemand Lib "epanet2.dll" (ByVal nodeIndex As Long, ByVal baseDemand As Single, ByVal patternName As String, ByVal demandName As String) As Long
|
||||||
|
Declare Function ENdeletedemand Lib "epanet2.dll" (ByVal nodeIndex As Long, ByVal demandIndex As Long) As Long
|
||||||
|
Declare Function ENgetdemandindex Lib "epanet2.dll" (ByVal nodeIndex As Long, ByVal demandName As String, demandIndex As Long) As Long
|
||||||
Declare Function ENgetnumdemands Lib "epanet2.dll" (ByVal nodeIndex As Long, numDemands As Long) As Long
|
Declare Function ENgetnumdemands Lib "epanet2.dll" (ByVal nodeIndex As Long, numDemands As Long) As Long
|
||||||
Declare Function ENgetbasedemand Lib "epanet2.dll" (ByVal nodeIndex As Long, ByVal demandIndex As Long, value As Single) As Long
|
Declare Function ENgetbasedemand Lib "epanet2.dll" (ByVal nodeIndex As Long, ByVal demandIndex As Long, value As Single) As Long
|
||||||
Declare Function ENsetbasedemand Lib "epanet2.dll" (ByVal nodeIndex As Long, ByVal demandIndex As Long, ByVal BaseDemand As Single) As Long
|
Declare Function ENsetbasedemand Lib "epanet2.dll" (ByVal nodeIndex As Long, ByVal demandIndex As Long, ByVal BaseDemand As Single) As Long
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ EXPORTS
|
|||||||
ENaddcurve = _ENaddcurve@4
|
ENaddcurve = _ENaddcurve@4
|
||||||
ENaddlink = _ENaddlink@20
|
ENaddlink = _ENaddlink@20
|
||||||
ENaddnode = _ENaddnode@12
|
ENaddnode = _ENaddnode@12
|
||||||
|
ENadddemand = _ENadddemand@16
|
||||||
ENaddpattern = _ENaddpattern@4
|
ENaddpattern = _ENaddpattern@4
|
||||||
ENaddrule = _ENaddrule@4
|
ENaddrule = _ENaddrule@4
|
||||||
ENclearreport = _ENclearreport@0
|
ENclearreport = _ENclearreport@0
|
||||||
@@ -14,6 +15,7 @@ EXPORTS
|
|||||||
ENcopyreport = _ENcopyreport@4
|
ENcopyreport = _ENcopyreport@4
|
||||||
ENdeletecontrol = _ENdeletecontrol@4
|
ENdeletecontrol = _ENdeletecontrol@4
|
||||||
ENdeletecurve = _ENdeletecurve@4
|
ENdeletecurve = _ENdeletecurve@4
|
||||||
|
ENdeletedemand = _ENdeletedemand@8
|
||||||
ENdeletelink = _ENdeletelink@8
|
ENdeletelink = _ENdeletelink@8
|
||||||
ENdeletenode = _ENdeletenode@8
|
ENdeletenode = _ENdeletenode@8
|
||||||
ENdeletepattern = _ENdeletepattern@4
|
ENdeletepattern = _ENdeletepattern@4
|
||||||
@@ -30,7 +32,8 @@ EXPORTS
|
|||||||
ENgetcurveindex = _ENgetcurveindex@8
|
ENgetcurveindex = _ENgetcurveindex@8
|
||||||
ENgetcurvelen = _ENgetcurvelen@8
|
ENgetcurvelen = _ENgetcurvelen@8
|
||||||
ENgetcurvetype = _ENgetcurvetype@8
|
ENgetcurvetype = _ENgetcurvetype@8
|
||||||
ENgetcurvevalue = _ENgetcurvevalue@16
|
ENgetcurvevalue = _ENgetcurvevalue@16
|
||||||
|
ENgetdemandindex = _ENgetdemandindex@12
|
||||||
ENgetdemandmodel = _ENgetdemandmodel@16
|
ENgetdemandmodel = _ENgetdemandmodel@16
|
||||||
ENgetdemandname = _ENgetdemandname@12
|
ENgetdemandname = _ENgetdemandname@12
|
||||||
ENgetdemandpattern = _ENgetdemandpattern@12
|
ENgetdemandpattern = _ENgetdemandpattern@12
|
||||||
|
|||||||
@@ -230,8 +230,15 @@ extern "C" {
|
|||||||
int DLLEXPORT ENsetdemandmodel(int model, EN_API_FLOAT_TYPE pmin,
|
int DLLEXPORT ENsetdemandmodel(int model, EN_API_FLOAT_TYPE pmin,
|
||||||
EN_API_FLOAT_TYPE preq, EN_API_FLOAT_TYPE pexp);
|
EN_API_FLOAT_TYPE preq, EN_API_FLOAT_TYPE pexp);
|
||||||
|
|
||||||
|
int DLLEXPORT ENadddemand(int nodeIndex, EN_API_FLOAT_TYPE baseDemand,
|
||||||
|
char *demandPattern, char *demandName);
|
||||||
|
|
||||||
|
int DLLEXPORT ENdeletedemand(int nodeIndex, int demandIndex);
|
||||||
|
|
||||||
int DLLEXPORT ENgetnumdemands(int nodeIndex, int *numDemands);
|
int DLLEXPORT ENgetnumdemands(int nodeIndex, int *numDemands);
|
||||||
|
|
||||||
|
int DLLEXPORT ENgetdemandindex(int nodeIndex, char *demandName, int *demandIndex);
|
||||||
|
|
||||||
int DLLEXPORT ENgetbasedemand(int nodeIndex, int demandIndex,
|
int DLLEXPORT ENgetbasedemand(int nodeIndex, int demandIndex,
|
||||||
EN_API_FLOAT_TYPE *baseDemand);
|
EN_API_FLOAT_TYPE *baseDemand);
|
||||||
|
|
||||||
|
|||||||
@@ -312,6 +312,9 @@ Public Const EN_R_IS_ACTIVE = 3
|
|||||||
'Nodal Demand Functions
|
'Nodal Demand Functions
|
||||||
Declare Function ENgetdemandmodel Lib "epanet2.dll" (type_ As Int32, pmin As Single, preq As Single, pexp As Single) As Int32
|
Declare Function ENgetdemandmodel Lib "epanet2.dll" (type_ As Int32, pmin As Single, preq As Single, pexp As Single) As Int32
|
||||||
Declare Function ENsetdemandmodel Lib "epanet2.dll" (ByVal type_ As Int32, ByVal pmin As Single, ByVal preq As Single, ByVal pexp As Single) As Int32
|
Declare Function ENsetdemandmodel Lib "epanet2.dll" (ByVal type_ As Int32, ByVal pmin As Single, ByVal preq As Single, ByVal pexp As Single) As Int32
|
||||||
|
Declare Function ENadddemand Lib "epanet2.dll" (ByVal nodeIndex As Int32, ByVal baseDemand As Single, ByVal patternName As String, ByVal demandName As String) As Int32
|
||||||
|
Declare Function ENdeletedemand Lib "epanet2.dll" (ByVal nodeIndex As Int32, ByVal demandIndex As Int32) As Int32
|
||||||
|
Declare Function ENgetdemandindex Lib "epanet2.dll" (ByVal nodeIndex As Int32, ByVal demandName As String, demandIndex As Int32) As Int32
|
||||||
Declare Function ENgetnumdemands Lib "epanet2.dll" (ByVal nodeIndex As Int32, numDemands As Int32) As Int32
|
Declare Function ENgetnumdemands Lib "epanet2.dll" (ByVal nodeIndex As Int32, numDemands As Int32) As Int32
|
||||||
Declare Function ENgetbasedemand Lib "epanet2.dll" (ByVal nodeIndex As Int32, ByVal demandIndex As Int32, value As Single) As Int32
|
Declare Function ENgetbasedemand Lib "epanet2.dll" (ByVal nodeIndex As Int32, ByVal demandIndex As Int32, value As Single) As Int32
|
||||||
Declare Function ENsetbasedemand Lib "epanet2.dll" (ByVal nodeIndex As Int32, ByVal demandIndex As Int32, ByVal BaseDemand As Single) As Int32
|
Declare Function ENsetbasedemand Lib "epanet2.dll" (ByVal nodeIndex As Int32, ByVal demandIndex As Int32, ByVal BaseDemand As Single) As Int32
|
||||||
|
|||||||
@@ -853,13 +853,6 @@ typedef struct Project *EN_Project;
|
|||||||
int DLLEXPORT EN_setjuncdata(EN_Project ph, int index, double elev, double dmnd,
|
int DLLEXPORT EN_setjuncdata(EN_Project ph, int index, double elev, double dmnd,
|
||||||
char *dmndpat);
|
char *dmndpat);
|
||||||
|
|
||||||
|
|
||||||
int DLLEXPORT EN_adddemand(EN_Project p, int node_index, double demand,
|
|
||||||
char *demand_pattern, const char *category_name, int *demand_index);
|
|
||||||
|
|
||||||
int DLLEXPORT EN_removedemand(EN_Project p, int node_index, int demand_index);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Sets a group of properties for a tank node.
|
@brief Sets a group of properties for a tank node.
|
||||||
@param ph an EPANET project handle.
|
@param ph an EPANET project handle.
|
||||||
@@ -940,6 +933,41 @@ typedef struct Project *EN_Project;
|
|||||||
int DLLEXPORT EN_setdemandmodel(EN_Project ph, int type, double pmin,
|
int DLLEXPORT EN_setdemandmodel(EN_Project ph, int type, double pmin,
|
||||||
double preq, double pexp);
|
double preq, double pexp);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief appends a new demand to a junction node demands list.
|
||||||
|
@param ph an EPANET project handle.
|
||||||
|
@param nodeIndex the index of a node (starting from 1).
|
||||||
|
@param baseDemand the demand's base value.
|
||||||
|
@param demandPattern the name of a time pattern used by the demand
|
||||||
|
@param demandName the name of the demand's category
|
||||||
|
@return an error code.
|
||||||
|
|
||||||
|
A NULL or blank string can be used for `demandPattern` and for `demandName` to indicate
|
||||||
|
that no time pattern or category name is associated with the demand.
|
||||||
|
*/
|
||||||
|
int DLLEXPORT EN_adddemand(EN_Project ph, int nodeIndex, double baseDemand,
|
||||||
|
char *demandPattern, char *demandName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief deletes a demand from a junction node.
|
||||||
|
@param ph an EPANET project handle.
|
||||||
|
@param nodeIndex the index of a node (starting from 1).
|
||||||
|
@param demandIndex the position of the demand in the node's demands list (starting from 1).
|
||||||
|
@return an error code.
|
||||||
|
*/
|
||||||
|
int DLLEXPORT EN_deletedemand(EN_Project ph, int nodeIndex, int demandIndex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Retrieves the index of a node's named demand category
|
||||||
|
@param nodeIndex the index of a node (starting from 1)
|
||||||
|
@param demandName the name of a demand category for the node
|
||||||
|
@param[out] demandIndex the index of the demand being sought
|
||||||
|
@return an error code
|
||||||
|
*/
|
||||||
|
int DLLEXPORT EN_getdemandindex(EN_Project p, int nodeIndex, char *demandName,
|
||||||
|
int *demandIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Retrieves the number of demand categories for a junction node.
|
@brief Retrieves the number of demand categories for a junction node.
|
||||||
@param ph an EPANET project handle.
|
@param ph an EPANET project handle.
|
||||||
|
|||||||
133
src/demand.c
133
src/demand.c
@@ -1,133 +0,0 @@
|
|||||||
/*
|
|
||||||
******************************************************************************
|
|
||||||
Project: OWA EPANET
|
|
||||||
Version: 2.2
|
|
||||||
Module: demand.c
|
|
||||||
Description: data for demand pattern list
|
|
||||||
Authors: see AUTHORS
|
|
||||||
Copyright: see AUTHORS
|
|
||||||
License: see LICENSE
|
|
||||||
Last Updated: 04/12/2019
|
|
||||||
******************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
#define _CRTDBG_MAP_ALLOC
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <crtdbg.h>
|
|
||||||
#else
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "demand.h"
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct demand_data_s
|
|
||||||
{
|
|
||||||
double base_demand;
|
|
||||||
int pattern_index;
|
|
||||||
char *category_name;
|
|
||||||
} demand_data_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
list_t *create_demand_list(double base_demand, int pattern_index, const char *category_name)
|
|
||||||
{
|
|
||||||
list_t *demand_list;
|
|
||||||
demand_data_t *demand_data;
|
|
||||||
|
|
||||||
demand_list = create_list(get_demand_data_size(), delete_demand_data);
|
|
||||||
if (!demand_list) return NULL;
|
|
||||||
|
|
||||||
demand_data = create_demand_data(base_demand, pattern_index, category_name);
|
|
||||||
if (!demand_data) return NULL;
|
|
||||||
|
|
||||||
append_list(demand_list, &demand_data);
|
|
||||||
|
|
||||||
return demand_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
demand_data_t *create_demand_data(double base_demand, int pattern_index, const char *category_name)
|
|
||||||
{
|
|
||||||
demand_data_t *demand_data = (demand_data_t *)malloc(sizeof(demand_data_t));
|
|
||||||
|
|
||||||
demand_data->base_demand = base_demand;
|
|
||||||
demand_data->pattern_index = pattern_index;
|
|
||||||
|
|
||||||
if (category_name)
|
|
||||||
demand_data->category_name = strdup(category_name);
|
|
||||||
else
|
|
||||||
demand_data->category_name = NULL;
|
|
||||||
|
|
||||||
return demand_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void delete_demand_data(void *data)
|
|
||||||
{
|
|
||||||
demand_data_t *demand_data = *(demand_data_t **)data;
|
|
||||||
|
|
||||||
if (demand_data->category_name)
|
|
||||||
free(demand_data->category_name);
|
|
||||||
|
|
||||||
free(demand_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t get_demand_data_size(void)
|
|
||||||
{
|
|
||||||
return sizeof(demand_data_t *);
|
|
||||||
}
|
|
||||||
|
|
||||||
demand_data_t *get_demand_data(list_node_t *lnode)
|
|
||||||
{
|
|
||||||
return *(demand_data_t **)get_data(lnode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool convert_units(list_node_t *lnode, double unit_conversion)
|
|
||||||
{
|
|
||||||
double base_demand = get_base_demand(lnode);
|
|
||||||
|
|
||||||
set_base_demand(lnode, base_demand/unit_conversion);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
double get_base_demand(list_node_t *lnode)
|
|
||||||
{
|
|
||||||
return get_demand_data(lnode)->base_demand;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_base_demand(list_node_t *lnode, double base_demand)
|
|
||||||
{
|
|
||||||
get_demand_data(lnode)->base_demand = base_demand;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_pattern_index(list_node_t *lnode)
|
|
||||||
{
|
|
||||||
return get_demand_data(lnode)->pattern_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_pattern_index(list_node_t *lnode, int pattern_index)
|
|
||||||
{
|
|
||||||
get_demand_data(lnode)->pattern_index = pattern_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *get_category_name(list_node_t *lnode)
|
|
||||||
// Be advised: caller must free memory returned
|
|
||||||
{
|
|
||||||
char *temp = get_demand_data(lnode)->category_name;
|
|
||||||
|
|
||||||
if (temp)
|
|
||||||
return strdup(temp);
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_category_name(list_node_t *lnode, const char *category_name)
|
|
||||||
{
|
|
||||||
free(get_demand_data(lnode)->category_name);
|
|
||||||
get_demand_data(lnode)->category_name = strdup(category_name);
|
|
||||||
}
|
|
||||||
63
src/demand.h
63
src/demand.h
@@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
******************************************************************************
|
|
||||||
Project: OWA EPANET
|
|
||||||
Version: 2.2
|
|
||||||
Module: demand.h
|
|
||||||
Description: data for demand pattern list
|
|
||||||
Authors: see AUTHORS
|
|
||||||
Copyright: see AUTHORS
|
|
||||||
License: see LICENSE
|
|
||||||
Last Updated: 04/12/2019
|
|
||||||
******************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DEMAND_H
|
|
||||||
#define DEMAND_H
|
|
||||||
|
|
||||||
|
|
||||||
#include "util/list.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// Forward declarations
|
|
||||||
typedef struct demand_data_s demand_data_t;
|
|
||||||
|
|
||||||
// demand list gets declared in types.h struct Snode
|
|
||||||
|
|
||||||
|
|
||||||
list_t *create_demand_list(double base_demand, int pattern_index, const char *category_name);
|
|
||||||
|
|
||||||
|
|
||||||
demand_data_t *create_demand_data(double base_demand, int pat_index, const char *cat_name);
|
|
||||||
|
|
||||||
void delete_demand_data(void *data);
|
|
||||||
|
|
||||||
size_t get_demand_data_size(void);
|
|
||||||
|
|
||||||
|
|
||||||
bool convert_units(list_node_t *lnode, double unit_conversion);
|
|
||||||
|
|
||||||
|
|
||||||
double get_base_demand(list_node_t *lnode);
|
|
||||||
void set_base_demand(list_node_t *lnode, double base_demand);
|
|
||||||
|
|
||||||
int get_pattern_index(list_node_t *lnode);
|
|
||||||
void set_pattern_index(list_node_t *lnode, int pattern_index);
|
|
||||||
|
|
||||||
char *get_category_name(list_node_t *lnode);
|
|
||||||
void set_category_name(list_node_t *lnode, const char *category_name);
|
|
||||||
|
|
||||||
// Make this private?
|
|
||||||
demand_data_t *get_demand_data(list_node_t *lnode);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* DEMAND_H */
|
|
||||||
399
src/epanet.c
399
src/epanet.c
@@ -20,7 +20,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
@@ -30,8 +29,6 @@
|
|||||||
#include "text.h"
|
#include "text.h"
|
||||||
#include "enumstxt.h"
|
#include "enumstxt.h"
|
||||||
|
|
||||||
#include "demand.h"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
#endif
|
#endif
|
||||||
@@ -1721,8 +1718,7 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType, int *index)
|
|||||||
Hydraul *hyd = &p->hydraul;
|
Hydraul *hyd = &p->hydraul;
|
||||||
Quality *qual = &p->quality;
|
Quality *qual = &p->quality;
|
||||||
|
|
||||||
int i, nIdx;
|
int i, nIdx, size;
|
||||||
int size;
|
|
||||||
Stank *tank;
|
Stank *tank;
|
||||||
Snode *node;
|
Snode *node;
|
||||||
Scontrol *control;
|
Scontrol *control;
|
||||||
@@ -1752,8 +1748,8 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType, int *index)
|
|||||||
net->Njuncs++;
|
net->Njuncs++;
|
||||||
nIdx = net->Njuncs;
|
nIdx = net->Njuncs;
|
||||||
node = &net->Node[nIdx];
|
node = &net->Node[nIdx];
|
||||||
|
node->D = NULL;
|
||||||
node->D = NULL;
|
adddemand(node, 0.0, 0, NULL);
|
||||||
|
|
||||||
// shift rest of Node array
|
// shift rest of Node array
|
||||||
for (i = net->Nnodes; i >= net->Njuncs; i--)
|
for (i = net->Nnodes; i >= net->Njuncs; i--)
|
||||||
@@ -1766,21 +1762,18 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType, int *index)
|
|||||||
{
|
{
|
||||||
net->Tank[i].Node += 1;
|
net->Tank[i].Node += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// shift indices of Links, if necessary
|
// shift indices of Links, if necessary
|
||||||
for (i = 1; i <= net->Nlinks; i++)
|
for (i = 1; i <= net->Nlinks; i++)
|
||||||
{
|
{
|
||||||
if (net->Link[i].N1 > net->Njuncs - 1) net->Link[i].N1 += 1;
|
if (net->Link[i].N1 > net->Njuncs - 1) net->Link[i].N1 += 1;
|
||||||
if (net->Link[i].N2 > net->Njuncs - 1) net->Link[i].N2 += 1;
|
if (net->Link[i].N2 > net->Njuncs - 1) net->Link[i].N2 += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// shift indices of tanks/reservoir nodes in controls
|
// shift indices of tanks/reservoir nodes in controls
|
||||||
for (i = 1; i <= net->Ncontrols; ++i)
|
for (i = 1; i <= net->Ncontrols; ++i)
|
||||||
{
|
{
|
||||||
control = &net->Control[i];
|
control = &net->Control[i];
|
||||||
if (control->Node > net->Njuncs - 1) control->Node += 1;
|
if (control->Node > net->Njuncs - 1) control->Node += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// adjust indices of tanks/reservoirs in Rule premises (see RULES.C)
|
// adjust indices of tanks/reservoirs in Rule premises (see RULES.C)
|
||||||
adjusttankrules(p);
|
adjusttankrules(p);
|
||||||
}
|
}
|
||||||
@@ -1854,7 +1847,6 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode)
|
|||||||
|
|
||||||
int i, nodeType, tankindex;
|
int i, nodeType, tankindex;
|
||||||
Snode *node;
|
Snode *node;
|
||||||
list_t *demand;
|
|
||||||
|
|
||||||
// Cannot modify network structure while solvers are active
|
// Cannot modify network structure while solvers are active
|
||||||
if (!p->Openflag) return 102;
|
if (!p->Openflag) return 102;
|
||||||
@@ -1886,10 +1878,7 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode)
|
|||||||
hashtable_delete(net->NodeHashTable, node->ID);
|
hashtable_delete(net->NodeHashTable, node->ID);
|
||||||
|
|
||||||
// Free memory allocated to node's demands, WQ source & comment
|
// Free memory allocated to node's demands, WQ source & comment
|
||||||
demand = node->D;
|
freedemands(node);
|
||||||
if (demand)
|
|
||||||
delete_list(demand);
|
|
||||||
|
|
||||||
free(node->S);
|
free(node->S);
|
||||||
free(node->Comment);
|
free(node->Comment);
|
||||||
|
|
||||||
@@ -2081,25 +2070,18 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case EN_BASEDEMAND:
|
case EN_BASEDEMAND:
|
||||||
v = 0.0;
|
|
||||||
// NOTE: primary demand category is first on demand list
|
// NOTE: primary demand category is first on demand list
|
||||||
if (index <= nJuncs)
|
if (index <= nJuncs)
|
||||||
{
|
{
|
||||||
list_t *demand = Node[index].D;
|
if (Node[index].D) v = Node[index].D->Base * Ucf[FLOW];
|
||||||
if (demand)
|
|
||||||
v = get_base_demand(head_list(demand, false));
|
|
||||||
}
|
}
|
||||||
v *= Ucf[FLOW];
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EN_PATTERN:
|
case EN_PATTERN:
|
||||||
v = 0.0;
|
|
||||||
// NOTE: primary demand category is first on demand list
|
// NOTE: primary demand category is first on demand list
|
||||||
if (index <= nJuncs)
|
if (index <= nJuncs)
|
||||||
{
|
{
|
||||||
list_t *demand = Node[index].D;
|
if (Node[index].D) v = (double)(Node[index].D->Pat);
|
||||||
if (demand)
|
|
||||||
v = get_pattern_index(head_list(demand, false));
|
|
||||||
}
|
}
|
||||||
else v = (double)(Tank[index - nJuncs].Pat);
|
else v = (double)(Tank[index - nJuncs].Pat);
|
||||||
break;
|
break;
|
||||||
@@ -2280,9 +2262,7 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|||||||
// NOTE: primary demand category is first on demand list
|
// NOTE: primary demand category is first on demand list
|
||||||
if (index <= nJuncs)
|
if (index <= nJuncs)
|
||||||
{
|
{
|
||||||
list_t *demand = Node[index].D;
|
if (Node[index].D) Node[index].D->Base = value / Ucf[FLOW];
|
||||||
if (demand)
|
|
||||||
set_base_demand(head_list(demand, false), value / Ucf[FLOW]);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -2292,9 +2272,7 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
|||||||
if (j < 0 || j > nPats) return 205;
|
if (j < 0 || j > nPats) return 205;
|
||||||
if (index <= nJuncs)
|
if (index <= nJuncs)
|
||||||
{
|
{
|
||||||
list_t *demand = Node[index].D;
|
if (Node[index].D) Node[index].D->Pat = j;
|
||||||
if (demand)
|
|
||||||
set_pattern_index(head_list(demand, false), j);
|
|
||||||
}
|
}
|
||||||
else Tank[index - nJuncs].Pat = j;
|
else Tank[index - nJuncs].Pat = j;
|
||||||
break;
|
break;
|
||||||
@@ -2542,81 +2520,33 @@ int DLLEXPORT EN_setjuncdata(EN_Project p, int index, double elev,
|
|||||||
**----------------------------------------------------------------
|
**----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
Network *net = &p->network;
|
int patIndex = 0;
|
||||||
|
Snode *node;
|
||||||
int i, patIndex = 0;
|
|
||||||
Snode *Node = net->Node;
|
|
||||||
|
|
||||||
// Check that junction exists
|
// Check that junction exists
|
||||||
if (!p->Openflag) return 102;
|
if (!p->Openflag) return 102;
|
||||||
if (index <= 0 || index > net->Njuncs) return 203;
|
if (index <= 0 || index > p->network.Njuncs) return 203;
|
||||||
|
|
||||||
// Check that demand pattern exists
|
// Check that demand pattern exists
|
||||||
if (strlen(dmndpat) > 0)
|
if (dmndpat && strlen(dmndpat) > 0)
|
||||||
{
|
{
|
||||||
for (i = 1; i <= net->Npats; i++)
|
if (EN_getpatternindex(p, dmndpat, &patIndex) > 0) return 205;
|
||||||
{
|
|
||||||
if (strcmp(dmndpat, net->Pattern[i].ID) == 0)
|
|
||||||
{
|
|
||||||
patIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (patIndex == 0) return 205;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign values to junction's parameters
|
// Assign demand parameters to junction's primary demand category
|
||||||
Node[index].El = elev / p->Ucf[ELEV];
|
node = &(p->network.Node[index]);
|
||||||
|
dmnd /= p->Ucf[FLOW];
|
||||||
list_t *demand_list = Node[index].D;
|
// Category exists - update its properties
|
||||||
if (!demand_list) {
|
if (node->D)
|
||||||
demand_list = create_list(get_demand_data_size(), delete_demand_data);
|
{
|
||||||
if (!demand_list) return 101;
|
(node->D)->Base = dmnd;
|
||||||
|
(node->D)->Pat = patIndex;
|
||||||
}
|
}
|
||||||
demand_data_t *demand_data = create_demand_data(dmnd/p->Ucf[FLOW], patIndex, NULL);
|
// No demand categories exist -- create a new one
|
||||||
if (!demand_data) return 101;
|
else if (!adddemand(node, dmnd, patIndex, NULL)) return 101;
|
||||||
|
|
||||||
append_list(demand_list, &demand_data);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DLLEXPORT EN_adddemand(EN_Project p, int node_index, double demand,
|
|
||||||
char *demand_pattern, const char *category_name, int *demand_key)
|
|
||||||
{
|
|
||||||
Network *net = &p->network;
|
|
||||||
|
|
||||||
int pattern_index, error = 0;
|
|
||||||
*demand_key = -1;
|
|
||||||
|
|
||||||
if (error = EN_getpatternindex(p, demand_pattern, &pattern_index) != 0) return error;
|
|
||||||
|
|
||||||
Snode *Node = net->Node;
|
|
||||||
list_t *demand_list = Node[node_index].D;
|
|
||||||
if (!demand_list) {
|
|
||||||
demand_list = create_demand_list(demand/p->Ucf[FLOW], pattern_index, category_name);
|
|
||||||
if (!demand_list) return 101;
|
|
||||||
|
|
||||||
Node[node_index].D = demand_list;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
demand_data_t *demand_data = create_demand_data(demand/p->Ucf[FLOW], pattern_index, category_name);
|
|
||||||
if (!demand_data) return 101;
|
|
||||||
|
|
||||||
*demand_key = append_list(demand_list, &demand_data);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DLLEXPORT EN_removedemand(EN_Project p, int node_index, int demand_key)
|
|
||||||
{
|
|
||||||
Network *net = &p->network;
|
|
||||||
Snode *Node = net->Node;
|
|
||||||
|
|
||||||
list_t *dlist = Node[node_index].D;
|
|
||||||
|
|
||||||
remove_node(dlist, demand_key);
|
|
||||||
|
|
||||||
|
// Assign new elevation value to junction
|
||||||
|
node->El = elev / p->Ucf[ELEV];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2793,6 +2723,138 @@ int DLLEXPORT EN_setdemandmodel(EN_Project p, int model, double pmin,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DLLEXPORT EN_adddemand(EN_Project p, int nodeIndex, double baseDemand,
|
||||||
|
char *demandPattern, char *demandName)
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
** Input: nodeIndex = node index
|
||||||
|
** baseDemand = baseline demand value
|
||||||
|
** demandPattern = name of demand's time pattern (can be NULL or empty)
|
||||||
|
** demandName = name of demand's category (can be NULL or empty)
|
||||||
|
** Returns: error code
|
||||||
|
** Purpose: adds a new demand category to a junction node
|
||||||
|
**----------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int patIndex = 0;
|
||||||
|
Snode *node;
|
||||||
|
|
||||||
|
// Check for valid arguments
|
||||||
|
if (!p->Openflag) return 102;
|
||||||
|
if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes) return 203;
|
||||||
|
if (demandPattern && strlen(demandPattern) > 0)
|
||||||
|
{
|
||||||
|
if (EN_getpatternindex(p, demandPattern, &patIndex) > 0) return 205;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do nothing if node is not a junction
|
||||||
|
if (nodeIndex > p->network.Njuncs) return 0;
|
||||||
|
|
||||||
|
// Add the new demand to the node's demands list
|
||||||
|
node = &(p->network.Node[nodeIndex]);
|
||||||
|
if (!adddemand(node, baseDemand / p->Ucf[FLOW], patIndex, demandName)) return 101;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DLLEXPORT EN_deletedemand(EN_Project p, int nodeIndex, int demandIndex)
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
** Input: nodeIndex = node index
|
||||||
|
** demandIndex = index of node's demand to be deleted
|
||||||
|
** Returns: error code
|
||||||
|
** Purpose: deletes an existing demand category from a junction node
|
||||||
|
**----------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
Pdemand d, dprev;
|
||||||
|
Snode *node;
|
||||||
|
int n = 1;
|
||||||
|
|
||||||
|
// Check for valid arguments
|
||||||
|
if (!p->Openflag) return 102;
|
||||||
|
if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes) return 203;
|
||||||
|
|
||||||
|
// Only junctions have demands
|
||||||
|
if (nodeIndex <= p->network.Njuncs)
|
||||||
|
{
|
||||||
|
// Find head of node's list of demands
|
||||||
|
node = &p->network.Node[nodeIndex];
|
||||||
|
d = node->D;
|
||||||
|
if (d == NULL) return 253;
|
||||||
|
dprev = d;
|
||||||
|
|
||||||
|
// Check if target demand is head of demand list
|
||||||
|
if (demandIndex == 1)
|
||||||
|
{
|
||||||
|
node->D = d->next;
|
||||||
|
free(d->Name);
|
||||||
|
free(d);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise locate target demand in demand list
|
||||||
|
while (d != NULL && n < demandIndex)
|
||||||
|
{
|
||||||
|
dprev = d;
|
||||||
|
d = d->next;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return error if target demand not found
|
||||||
|
if (d == NULL) return 253;
|
||||||
|
|
||||||
|
// Link the demands that precede and follow the target
|
||||||
|
dprev->next = d->next;
|
||||||
|
|
||||||
|
// Delete the target demand
|
||||||
|
free(d->Name);
|
||||||
|
free(d);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DLLEXPORT EN_getdemandindex(EN_Project p, int nodeIndex, char *demandName,
|
||||||
|
int *demandIndex)
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
** Input: nodeIndex = node index
|
||||||
|
** demandName = name of demand being sought
|
||||||
|
** Output: demandIndex = index of demand being sought
|
||||||
|
** Returns: error code
|
||||||
|
** Purpose: retrieves the position of a named demand category
|
||||||
|
** in a node's list of demands
|
||||||
|
**----------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
Pdemand d;
|
||||||
|
int n = 0;
|
||||||
|
int nameEmpty = FALSE;
|
||||||
|
int found = FALSE;
|
||||||
|
|
||||||
|
// Check for valid arguments
|
||||||
|
*demandIndex = 0;
|
||||||
|
if (!p->Openflag) return 102;
|
||||||
|
if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes) return 203;
|
||||||
|
if (demandName == NULL) return 253;
|
||||||
|
|
||||||
|
// Check if target name is empty
|
||||||
|
if (strlen(demandName) == 0) nameEmpty = TRUE;
|
||||||
|
|
||||||
|
// Locate target demand in node's demands list
|
||||||
|
for (d = p->network.Node[nodeIndex].D; d != NULL; d = d->next)
|
||||||
|
{
|
||||||
|
n++;
|
||||||
|
if (d->Name == NULL)
|
||||||
|
{
|
||||||
|
if (nameEmpty) found = TRUE;;
|
||||||
|
}
|
||||||
|
else if (strcmp(d->Name, demandName) == 0) found = TRUE;
|
||||||
|
if (found) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return target demand's index
|
||||||
|
if (!found) return 253;
|
||||||
|
*demandIndex = n;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int DLLEXPORT EN_getnumdemands(EN_Project p, int nodeIndex, int *numDemands)
|
int DLLEXPORT EN_getnumdemands(EN_Project p, int nodeIndex, int *numDemands)
|
||||||
/*----------------------------------------------------------------
|
/*----------------------------------------------------------------
|
||||||
** Input: nodeIndex = node index
|
** Input: nodeIndex = node index
|
||||||
@@ -2802,20 +2864,16 @@ int DLLEXPORT EN_getnumdemands(EN_Project p, int nodeIndex, int *numDemands)
|
|||||||
**----------------------------------------------------------------
|
**----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
//Pdemand d;
|
Pdemand d;
|
||||||
//int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
// Check for valid arguments
|
// Check for valid arguments
|
||||||
if (!p->Openflag) return 102;
|
if (!p->Openflag) return 102;
|
||||||
if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes) return 203;
|
if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes) return 203;
|
||||||
|
|
||||||
// Count the number of demand categories
|
// Count the number of demand categories assigned to node
|
||||||
list_t *demand_list = p->network.Node[nodeIndex].D;
|
for (d = p->network.Node[nodeIndex].D; d != NULL; d = d->next) n++;
|
||||||
if (demand_list)
|
*numDemands = n;
|
||||||
*numDemands = size_list(demand_list);
|
|
||||||
else
|
|
||||||
*numDemands = 0;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2830,22 +2888,19 @@ int DLLEXPORT EN_getbasedemand(EN_Project p, int nodeIndex, int demandIndex,
|
|||||||
**----------------------------------------------------------------
|
**----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
|
Pdemand d;
|
||||||
|
|
||||||
// Check for valid arguments
|
// Check for valid arguments
|
||||||
|
*baseDemand = 0.0;
|
||||||
if (!p->Openflag) return 102;
|
if (!p->Openflag) return 102;
|
||||||
if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes) return 203;
|
if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes) return 203;
|
||||||
|
|
||||||
// Retrieve demand for specified category
|
// Locate target demand in node's demands list
|
||||||
if (nodeIndex <= p->network.Njuncs)
|
d = finddemand(p->network.Node[nodeIndex].D, demandIndex);
|
||||||
{
|
if (d == NULL) return 253;
|
||||||
// Locate demand category record and assign demandName to it
|
|
||||||
list_t *dlist = p->network.Node[nodeIndex].D;
|
// Retrieve target demand's base value
|
||||||
list_node_t *lnode = get_nth_list(dlist, demandIndex);
|
*baseDemand = d->Base * p->Ucf[FLOW];
|
||||||
if (!lnode)
|
|
||||||
return 253;
|
|
||||||
else
|
|
||||||
*baseDemand = get_base_demand(lnode) * p->Ucf[FLOW];
|
|
||||||
}
|
|
||||||
else *baseDemand = (double)(0.0);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2861,30 +2916,18 @@ int DLLEXPORT EN_setbasedemand(EN_Project p, int nodeIndex, int demandIndex,
|
|||||||
**----------------------------------------------------------------
|
**----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
|
Pdemand d;
|
||||||
|
|
||||||
// Check for valid arguments
|
// Check for valid arguments
|
||||||
if (!p->Openflag) return 102;
|
if (!p->Openflag) return 102;
|
||||||
if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes) return 203;
|
if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes) return 203;
|
||||||
|
|
||||||
// Set baseline demand for specified category
|
// Locate target demand in node's demands list
|
||||||
if (nodeIndex <= p->network.Njuncs)
|
d = finddemand(p->network.Node[nodeIndex].D, demandIndex);
|
||||||
{
|
if (d == NULL) return 253;
|
||||||
list_t *dlist = p->network.Node[nodeIndex].D;
|
|
||||||
// If demand list is null create one and set demand
|
|
||||||
if (!dlist) {
|
|
||||||
dlist = create_demand_list(baseDemand / p->Ucf[FLOW], 0, NULL);
|
|
||||||
if (!dlist) return 101;
|
|
||||||
|
|
||||||
p->network.Node[nodeIndex].D = dlist;
|
// Assign new base value to target demand
|
||||||
}
|
d->Base = baseDemand / p->Ucf[FLOW];
|
||||||
// else find the demand entry and set demand
|
|
||||||
else {
|
|
||||||
list_node_t *lnode = get_nth_list(dlist, demandIndex);
|
|
||||||
if (!lnode)
|
|
||||||
return 253;
|
|
||||||
else
|
|
||||||
set_base_demand(lnode, baseDemand / p->Ucf[FLOW]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2899,7 +2942,7 @@ int DLLEXPORT EN_getdemandname(EN_Project p, int nodeIndex, int demandIndex,
|
|||||||
**----------------------------------------------------------------
|
**----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
char *temp = NULL;
|
Pdemand d;
|
||||||
|
|
||||||
strcpy(demandName, "");
|
strcpy(demandName, "");
|
||||||
|
|
||||||
@@ -2907,22 +2950,12 @@ int DLLEXPORT EN_getdemandname(EN_Project p, int nodeIndex, int demandIndex,
|
|||||||
if (!p->Openflag) return 102;
|
if (!p->Openflag) return 102;
|
||||||
if (nodeIndex <= 0 || nodeIndex > p->network.Njuncs) return 203;
|
if (nodeIndex <= 0 || nodeIndex > p->network.Njuncs) return 203;
|
||||||
|
|
||||||
// Locate demand category record and retrieve its name
|
// Locate target demand in node's demands list
|
||||||
list_t *dlist = p->network.Node[nodeIndex].D;
|
d = finddemand(p->network.Node[nodeIndex].D, demandIndex);
|
||||||
if (dlist) {
|
if (d == NULL) return 253;
|
||||||
list_node_t *lnode = get_nth_list(dlist, demandIndex);
|
|
||||||
if (!lnode)
|
|
||||||
return 253;
|
|
||||||
else
|
|
||||||
temp = get_category_name(lnode);
|
|
||||||
|
|
||||||
if (temp) {
|
|
||||||
strcpy(demandName, temp);
|
|
||||||
free(temp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else return 253;
|
|
||||||
|
|
||||||
|
// Retrieve target demand's category name
|
||||||
|
if (d->Name) strcpy(demandName, d->Name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2938,29 +2971,18 @@ int DLLEXPORT EN_setdemandname(EN_Project p, int nodeIndex, int demandIndex,
|
|||||||
**----------------------------------------------------------------
|
**----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
|
Pdemand d;
|
||||||
|
|
||||||
// Check for valid arguments
|
// Check for valid arguments
|
||||||
if (!p->Openflag) return 102;
|
if (!p->Openflag) return 102;
|
||||||
if (nodeIndex <= 0 || nodeIndex > p->network.Njuncs) return 203;
|
if (nodeIndex <= 0 || nodeIndex > p->network.Njuncs) return 203;
|
||||||
|
|
||||||
// Check that demandName is not too long
|
// Locate target demand in node's demands list
|
||||||
if (strlen(demandName) > MAXID) return 252;
|
d = finddemand(p->network.Node[nodeIndex].D, demandIndex);
|
||||||
|
if (d == NULL) return 253;
|
||||||
|
|
||||||
// Locate demand category record and assign demandName to it
|
// Assign category name to target demand
|
||||||
list_t *dlist = p->network.Node[nodeIndex].D;
|
d->Name = xstrcpy(&d->Name, demandName, MAXID);
|
||||||
if (!dlist) {
|
|
||||||
dlist = create_demand_list(0, 0, demandName);
|
|
||||||
if (!dlist) return 101;
|
|
||||||
|
|
||||||
p->network.Node[nodeIndex].D = dlist;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
list_node_t *lnode = get_nth_list(dlist, demandIndex);
|
|
||||||
if (!lnode)
|
|
||||||
return 253;
|
|
||||||
else
|
|
||||||
set_category_name(lnode, demandName);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2976,18 +2998,19 @@ int DLLEXPORT EN_getdemandpattern(EN_Project p, int nodeIndex, int demandIndex,
|
|||||||
**----------------------------------------------------------------
|
**----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
|
Pdemand d;
|
||||||
|
|
||||||
// Check for valid arguments
|
// Check for valid arguments
|
||||||
|
*patIndex = 0;
|
||||||
if (!p->Openflag) return 102;
|
if (!p->Openflag) return 102;
|
||||||
if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes) return 203;
|
if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes) return 203;
|
||||||
|
|
||||||
// Locate demand category record and assign demandName to it
|
// Locate target demand in node's demand list
|
||||||
list_t *dlist = p->network.Node[nodeIndex].D;
|
d = finddemand(p->network.Node[nodeIndex].D, demandIndex);
|
||||||
list_node_t *lnode = get_nth_list(dlist, demandIndex);
|
if (d == NULL) return 253;
|
||||||
if (!lnode)
|
|
||||||
return 253;
|
|
||||||
else
|
|
||||||
*patIndex = get_pattern_index(lnode);
|
|
||||||
|
|
||||||
|
// Retrieve that demand's pattern index
|
||||||
|
*patIndex = d->Pat;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3005,29 +3028,19 @@ int DLLEXPORT EN_setdemandpattern(EN_Project p, int nodeIndex, int demandIndex,
|
|||||||
{
|
{
|
||||||
Network *net = &p->network;
|
Network *net = &p->network;
|
||||||
|
|
||||||
|
Pdemand d;
|
||||||
|
|
||||||
// Check for valid arguments
|
// Check for valid arguments
|
||||||
if (!p->Openflag) return 102;
|
if (!p->Openflag) return 102;
|
||||||
if (nodeIndex <= 0 || nodeIndex > net->Nnodes) return 203;
|
if (nodeIndex <= 0 || nodeIndex > net->Nnodes) return 203;
|
||||||
if (patIndex <= 0 || patIndex > net->Npats) return 205;
|
if (patIndex < 0 || patIndex > net->Npats) return 205;
|
||||||
|
|
||||||
// Locate demand category record and assign time pattern to it
|
// Locate target demand in node's demand list
|
||||||
if (nodeIndex <= net->Njuncs) {
|
d = finddemand(p->network.Node[nodeIndex].D, demandIndex);
|
||||||
|
if (d == NULL) return 253;
|
||||||
|
|
||||||
list_t *dlist = p->network.Node[nodeIndex].D;
|
// Assign new time pattern to target demand
|
||||||
if (!dlist) {
|
d->Pat = patIndex;
|
||||||
dlist = create_demand_list(0, patIndex, NULL);
|
|
||||||
if (!dlist) return 101;
|
|
||||||
|
|
||||||
p->network.Node[nodeIndex].D = dlist;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
list_node_t *lnode = get_nth_list(dlist, demandIndex);
|
|
||||||
if (!lnode)
|
|
||||||
return 253;
|
|
||||||
else
|
|
||||||
set_pattern_index(lnode, patIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -385,6 +385,22 @@ int DLLEXPORT ENsetdemandmodel(int model, EN_API_FLOAT_TYPE pmin,
|
|||||||
return EN_setdemandmodel(_defaultProject, model, pmin, preq, pexp);
|
return EN_setdemandmodel(_defaultProject, model, pmin, preq, pexp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DLLEXPORT ENadddemand(int nodeIndex, EN_API_FLOAT_TYPE baseDemand,
|
||||||
|
char *demandPattern, char *demandName)
|
||||||
|
{
|
||||||
|
return EN_adddemand(_defaultProject, nodeIndex, baseDemand, demandPattern, demandName);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DLLEXPORT ENdeletedemand(int nodeIndex, int demandIndex)
|
||||||
|
{
|
||||||
|
return EN_deletedemand(_defaultProject, nodeIndex, demandIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DLLEXPORT ENgetdemandindex(int nodeIndex, char *demandName, int *demandIndex)
|
||||||
|
{
|
||||||
|
return EN_getdemandindex(_defaultProject, nodeIndex, demandName, demandIndex);
|
||||||
|
}
|
||||||
|
|
||||||
int DLLEXPORT ENgetnumdemands(int nodeIndex, int *numDemands)
|
int DLLEXPORT ENgetnumdemands(int nodeIndex, int *numDemands)
|
||||||
{
|
{
|
||||||
return EN_getnumdemands(_defaultProject, nodeIndex, numDemands);
|
return EN_getnumdemands(_defaultProject, nodeIndex, numDemands);
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ int findpump(Network *, int);
|
|||||||
int findpattern(Network *, char *);
|
int findpattern(Network *, char *);
|
||||||
int findcurve(Network *, char *);
|
int findcurve(Network *, char *);
|
||||||
|
|
||||||
|
Pdemand finddemand(Pdemand, int);
|
||||||
|
int adddemand(Snode *, double, int, char *);
|
||||||
|
void freedemands(Snode *);
|
||||||
|
|
||||||
void adjustpatterns(Network *, int);
|
void adjustpatterns(Network *, int);
|
||||||
void adjustcurves(Network *, int);
|
void adjustcurves(Network *, int);
|
||||||
int resizecurve(Scurve *, int);
|
int resizecurve(Scurve *, int);
|
||||||
|
|||||||
@@ -27,9 +27,6 @@
|
|||||||
#include "funcs.h"
|
#include "funcs.h"
|
||||||
#include "text.h"
|
#include "text.h"
|
||||||
|
|
||||||
#include "demand.h"
|
|
||||||
|
|
||||||
|
|
||||||
const double QZERO = 1.e-6; // Equivalent to zero flow in cfs
|
const double QZERO = 1.e-6; // Equivalent to zero flow in cfs
|
||||||
|
|
||||||
// Imported functions
|
// Imported functions
|
||||||
@@ -556,7 +553,7 @@ void demands(Project *pr)
|
|||||||
int i ,j, n;
|
int i ,j, n;
|
||||||
long k, p;
|
long k, p;
|
||||||
double djunc, sum;
|
double djunc, sum;
|
||||||
// Pdemand demand;
|
Pdemand demand;
|
||||||
|
|
||||||
// Determine total elapsed number of pattern periods
|
// Determine total elapsed number of pattern periods
|
||||||
p = (time->Htime + time->Pstart) / time->Pstep;
|
p = (time->Htime + time->Pstart) / time->Pstep;
|
||||||
@@ -566,19 +563,15 @@ void demands(Project *pr)
|
|||||||
for (i = 1; i <= net->Njuncs; i++)
|
for (i = 1; i <= net->Njuncs; i++)
|
||||||
{
|
{
|
||||||
sum = 0.0;
|
sum = 0.0;
|
||||||
list_t *dlist = net->Node[i].D;
|
for (demand = net->Node[i].D; demand != NULL; demand = demand->next)
|
||||||
|
{
|
||||||
if (dlist) {
|
// pattern period (k) = (elapsed periods) modulus (periods per pattern)
|
||||||
for (list_node_t *lnode = first_list(dlist); done_list(lnode); lnode = next_list(lnode))
|
j = demand->Pat;
|
||||||
{
|
k = p % (long)net->Pattern[j].Length;
|
||||||
// pattern period (k) = (elapsed periods) modulus (periods per pattern)
|
djunc = (demand->Base) * net->Pattern[j].F[k] * hyd->Dmult;
|
||||||
j = get_pattern_index(lnode);
|
if (djunc > 0.0) hyd->Dsystem += djunc;
|
||||||
k = p % (long)net->Pattern[j].Length;
|
sum += djunc;
|
||||||
djunc = (get_base_demand(lnode)) * net->Pattern[j].F[k] * hyd->Dmult;
|
}
|
||||||
if (djunc > 0.0) hyd->Dsystem += djunc;
|
|
||||||
sum += djunc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hyd->NodeDemand[i] = sum;
|
hyd->NodeDemand[i] = sum;
|
||||||
|
|
||||||
// Initialize pressure dependent demand
|
// Initialize pressure dependent demand
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ Last Updated: 04/03/2019
|
|||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "text.h"
|
#include "text.h"
|
||||||
|
|
||||||
#include "demand.h"
|
|
||||||
|
|
||||||
// Defined in enumstxt.h in EPANET.C
|
// Defined in enumstxt.h in EPANET.C
|
||||||
extern char *LinkTxt[];
|
extern char *LinkTxt[];
|
||||||
@@ -121,48 +120,6 @@ void saveauxdata(Project *pr, FILE *f)
|
|||||||
InFile = NULL;
|
InFile = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void write_demands(Project *pr, FILE *f) {
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
Snode *node = NULL;
|
|
||||||
list_node_t *lnode = NULL;
|
|
||||||
char *temp = NULL;
|
|
||||||
|
|
||||||
char s[MAXLINE + 1],
|
|
||||||
s1[MAXLINE + 1];
|
|
||||||
|
|
||||||
double ucf = pr->Ucf[DEMAND];
|
|
||||||
Network *net = &pr->network;
|
|
||||||
|
|
||||||
fprintf(f, "\n\n");
|
|
||||||
fprintf(f, s_DEMANDS);
|
|
||||||
|
|
||||||
for (i = 1; i <= net->Njuncs; i++) {
|
|
||||||
node = &net->Node[i];
|
|
||||||
if (node->D) {
|
|
||||||
for (lnode = first_list(node->D); done_list(lnode); lnode = next_list(lnode)) {
|
|
||||||
if (lnode) {
|
|
||||||
sprintf(s, " %-31s %14.6f", node->ID, ucf * get_base_demand(lnode));
|
|
||||||
|
|
||||||
if
|
|
||||||
((j = get_pattern_index(lnode)) > 0) sprintf(s1, " %-31s", net->Pattern[j].ID);
|
|
||||||
else
|
|
||||||
strcpy(s1, " ");
|
|
||||||
|
|
||||||
fprintf(f, "\n%s %-31s", s, s1);
|
|
||||||
|
|
||||||
if (temp = get_category_name(lnode)) {
|
|
||||||
fprintf(f, " ;%s", temp);
|
|
||||||
free(temp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int saveinpfile(Project *pr, const char *fname)
|
int saveinpfile(Project *pr, const char *fname)
|
||||||
/*
|
/*
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
@@ -179,9 +136,9 @@ int saveinpfile(Project *pr, const char *fname)
|
|||||||
Times *time = &pr->times;
|
Times *time = &pr->times;
|
||||||
|
|
||||||
int i, j, n;
|
int i, j, n;
|
||||||
double d, kc, ke, km;
|
double d, kc, ke, km, ucf;
|
||||||
char s[MAXLINE + 1], s1[MAXLINE + 1], s2[MAXLINE + 1];
|
char s[MAXLINE + 1], s1[MAXLINE + 1], s2[MAXLINE + 1];
|
||||||
//Pdemand demand;
|
Pdemand demand;
|
||||||
Psource source;
|
Psource source;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
Slink *link;
|
Slink *link;
|
||||||
@@ -371,7 +328,21 @@ int saveinpfile(Project *pr, const char *fname)
|
|||||||
|
|
||||||
|
|
||||||
// Write [DEMANDS] section
|
// Write [DEMANDS] section
|
||||||
write_demands(pr, f);
|
fprintf(f, "\n\n");
|
||||||
|
fprintf(f, s_DEMANDS);
|
||||||
|
ucf = pr->Ucf[DEMAND];
|
||||||
|
for (i = 1; i <= net->Njuncs; i++)
|
||||||
|
{
|
||||||
|
node = &net->Node[i];
|
||||||
|
for (demand = node->D; demand != NULL; demand = demand->next)
|
||||||
|
{
|
||||||
|
sprintf(s, " %-31s %14.6f", node->ID, ucf * demand->Base);
|
||||||
|
if ((j = demand->Pat) > 0) sprintf(s1, " %-31s", net->Pattern[j].ID);
|
||||||
|
else strcpy(s1, " ");
|
||||||
|
fprintf(f, "\n%s %-31s", s, s1);
|
||||||
|
if (demand->Name) fprintf(f, " ;%s", demand->Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Write [EMITTERS] section
|
// Write [EMITTERS] section
|
||||||
|
|||||||
38
src/input1.c
38
src/input1.c
@@ -20,11 +20,8 @@ Last Updated: 04/03/2019
|
|||||||
#endif
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "demand.h"
|
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "funcs.h"
|
#include "funcs.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
@@ -222,9 +219,9 @@ void adjustdata(Project *pr)
|
|||||||
|
|
||||||
int i;
|
int i;
|
||||||
double ucf; // Unit conversion factor
|
double ucf; // Unit conversion factor
|
||||||
//Pdemand demand; // Pointer to demand record
|
Pdemand demand; // Pointer to demand record
|
||||||
Slink *link;
|
Slink *link;
|
||||||
//Snode *node;
|
Snode *node;
|
||||||
Stank *tank;
|
Stank *tank;
|
||||||
|
|
||||||
// Use 1 hr pattern & report time step if none specified
|
// Use 1 hr pattern & report time step if none specified
|
||||||
@@ -334,14 +331,14 @@ void adjustdata(Project *pr)
|
|||||||
|
|
||||||
// Use default pattern if none assigned to a demand
|
// Use default pattern if none assigned to a demand
|
||||||
parser->DefPat = findpattern(net, parser->DefPatID);
|
parser->DefPat = findpattern(net, parser->DefPatID);
|
||||||
if (parser->DefPat > 0) {
|
if (parser->DefPat > 0) for (i = 1; i <= net->Nnodes; i++)
|
||||||
for (i = 1; i <= net->Nnodes; i++) {
|
{
|
||||||
for (list_node_t *lnode = first_list((&net->Node[i])->D); done_list(lnode); lnode = next_list(lnode)) {
|
node = &net->Node[i];
|
||||||
if (get_pattern_index(lnode) == 0)
|
for (demand = node->D; demand != NULL; demand = demand->next)
|
||||||
set_pattern_index(lnode, parser->DefPat);
|
{
|
||||||
}
|
if (demand->Pat == 0) demand->Pat = parser->DefPat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove QUALITY as a reporting variable if no WQ analysis
|
// Remove QUALITY as a reporting variable if no WQ analysis
|
||||||
if (qual->Qualflag == NONE) rpt->Field[QUALITY].Enabled = FALSE;
|
if (qual->Qualflag == NONE) rpt->Field[QUALITY].Enabled = FALSE;
|
||||||
@@ -544,7 +541,7 @@ void convertunits(Project *pr)
|
|||||||
|
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
double ucf; // Unit conversion factor
|
double ucf; // Unit conversion factor
|
||||||
//Pdemand demand; // Pointer to demand record
|
Pdemand demand; // Pointer to demand record
|
||||||
Snode *node;
|
Snode *node;
|
||||||
Stank *tank;
|
Stank *tank;
|
||||||
Slink *link;
|
Slink *link;
|
||||||
@@ -564,15 +561,10 @@ void convertunits(Project *pr)
|
|||||||
for (i = 1; i <= net->Njuncs; i++)
|
for (i = 1; i <= net->Njuncs; i++)
|
||||||
{
|
{
|
||||||
node = &net->Node[i];
|
node = &net->Node[i];
|
||||||
list_t *dlist = node->D;
|
for (demand = node->D; demand != NULL; demand = demand->next)
|
||||||
if (dlist) {
|
{
|
||||||
for (list_node_t *lnode = first_list(dlist); done_list(lnode); lnode = next_list(lnode))
|
demand->Base /= pr->Ucf[DEMAND];
|
||||||
convert_units(lnode, pr->Ucf[DEMAND]);
|
}
|
||||||
}
|
|
||||||
// for (demand = node->D; demand != NULL; demand = demand->next)
|
|
||||||
// {
|
|
||||||
// demand->Base /= pr->Ucf[DEMAND];
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hyd->Pmin /= pr->Ucf[PRESSURE];
|
hyd->Pmin /= pr->Ucf[PRESSURE];
|
||||||
|
|||||||
58
src/input3.c
58
src/input3.c
@@ -20,10 +20,8 @@ Last Updated: 04/03/2019
|
|||||||
#endif
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "demand.h"
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "funcs.h"
|
#include "funcs.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
@@ -86,10 +84,6 @@ int juncdata(Project *pr)
|
|||||||
int njuncs; // number of network junction nodes
|
int njuncs; // number of network junction nodes
|
||||||
double el, // elevation
|
double el, // elevation
|
||||||
y = 0.0; // base demand
|
y = 0.0; // base demand
|
||||||
|
|
||||||
list_t *demand_list = NULL; // demand list
|
|
||||||
|
|
||||||
|
|
||||||
Snode *node;
|
Snode *node;
|
||||||
|
|
||||||
// Add new junction to data base
|
// Add new junction to data base
|
||||||
@@ -122,13 +116,9 @@ int juncdata(Project *pr)
|
|||||||
node->Type = JUNCTION;
|
node->Type = JUNCTION;
|
||||||
node->Comment = xstrcpy(&node->Comment, parser->Comment, MAXMSG);
|
node->Comment = xstrcpy(&node->Comment, parser->Comment, MAXMSG);
|
||||||
|
|
||||||
// create demand data only if a demand has been specified
|
// Create a demand for the junction and use NodeDemand as an indicator
|
||||||
if (y != 0.0) {
|
// to be used when processing demands from the [DEMANDS] section
|
||||||
demand_list = create_demand_list(y, p, NULL);
|
if (!adddemand(node, y, p, NULL)) return 101;
|
||||||
if (!demand_list) return 101;
|
|
||||||
}
|
|
||||||
node->D = demand_list;
|
|
||||||
|
|
||||||
hyd->NodeDemand[njuncs] = y;
|
hyd->NodeDemand[njuncs] = y;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -713,11 +703,7 @@ int demanddata(Project *pr)
|
|||||||
int j, n, p = 0;
|
int j, n, p = 0;
|
||||||
double y;
|
double y;
|
||||||
|
|
||||||
list_t *demand_list = NULL;
|
Pdemand demand;
|
||||||
demand_data_t *demand_data = NULL;
|
|
||||||
|
|
||||||
//Pdemand demand;
|
|
||||||
//Pdemand cur_demand;
|
|
||||||
|
|
||||||
// Extract data from tokens
|
// Extract data from tokens
|
||||||
n = parser->Ntokens;
|
n = parser->Ntokens;
|
||||||
@@ -741,27 +727,23 @@ int demanddata(Project *pr)
|
|||||||
if (p == 0) return setError(parser, 2, 205);
|
if (p == 0) return setError(parser, 2, 205);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Replace any demand entered in [JUNCTIONS] section
|
||||||
// if no demands were specified in [JUNCTIONS] create the list here
|
demand = net->Node[j].D;
|
||||||
demand_list = net->Node[j].D;
|
if (demand && hyd->NodeDemand[j] != MISSING)
|
||||||
if (demand_list == NULL) {
|
{
|
||||||
demand_list = create_list(get_demand_data_size(), delete_demand_data);
|
// First category encountered will overwrite demand category
|
||||||
if (demand_list == NULL) return 101;
|
// created when junction was read from [JUNCTIONS] section
|
||||||
net->Node[j].D = demand_list;
|
demand->Base = y;
|
||||||
}
|
demand->Pat = p;
|
||||||
|
if (parser->Comment[0])
|
||||||
// else replace the demand data entered in [JUNCTIONS] section
|
{
|
||||||
else if (size_list(demand_list) == 1) {
|
demand->Name = xstrcpy(&demand->Name, parser->Comment, MAXID);
|
||||||
list_node_t *lnode = head_list(demand_list, true);
|
}
|
||||||
delete_node(demand_list, lnode);
|
hyd->NodeDemand[j] = MISSING; // marker - next iteration will append a new category.
|
||||||
}
|
}
|
||||||
|
|
||||||
// append the data to the list
|
|
||||||
demand_data = create_demand_data(y, p, parser->Comment);
|
|
||||||
if (demand_data == NULL) return 101;
|
|
||||||
|
|
||||||
append_list(demand_list, &demand_data);
|
|
||||||
|
|
||||||
|
// Otherwise add new demand to junction
|
||||||
|
else if (!adddemand(&net->Node[j], y, p, parser->Comment) > 0) return 101;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
106
src/project.c
106
src/project.c
@@ -29,7 +29,6 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "funcs.h"
|
#include "funcs.h"
|
||||||
|
|
||||||
#include "demand.h"
|
|
||||||
|
|
||||||
int openfiles(Project *pr, const char *f1, const char *f2, const char *f3)
|
int openfiles(Project *pr, const char *f1, const char *f2, const char *f3)
|
||||||
/*----------------------------------------------------------------
|
/*----------------------------------------------------------------
|
||||||
@@ -387,7 +386,6 @@ void freedata(Project *pr)
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
//Pdemand demand, nextdemand;
|
|
||||||
|
|
||||||
// Free memory for computed results
|
// Free memory for computed results
|
||||||
free(pr->hydraul.NodeDemand);
|
free(pr->hydraul.NodeDemand);
|
||||||
@@ -405,12 +403,8 @@ void freedata(Project *pr)
|
|||||||
{
|
{
|
||||||
for (j = 1; j <= pr->parser.MaxNodes; j++)
|
for (j = 1; j <= pr->parser.MaxNodes; j++)
|
||||||
{
|
{
|
||||||
// Free memory used for demand category list
|
// Free memory used for demands and WQ source data
|
||||||
list_t *demand = pr->network.Node[j].D;
|
freedemands(&(pr->network.Node[j]));
|
||||||
if(demand)
|
|
||||||
delete_list(demand);
|
|
||||||
|
|
||||||
// Free memory used for WQ source data
|
|
||||||
free(pr->network.Node[j].S);
|
free(pr->network.Node[j].S);
|
||||||
free(pr->network.Node[j].Comment);
|
free(pr->network.Node[j].Comment);
|
||||||
}
|
}
|
||||||
@@ -471,6 +465,83 @@ void freedata(Project *pr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pdemand finddemand(Pdemand d, int index)
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
** Input: d = pointer to start of a list of demands
|
||||||
|
** index = the position of the demand to retrieve
|
||||||
|
** Output: none
|
||||||
|
** Returns: the demand at the requested position
|
||||||
|
** Purpose: finds the demand at a given position in a demand list
|
||||||
|
**----------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int n = 1;
|
||||||
|
if (index <= 0)return NULL;
|
||||||
|
while (d)
|
||||||
|
{
|
||||||
|
if (n == index) break;
|
||||||
|
n++;
|
||||||
|
d = d->next;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
int adddemand(Snode *node, double dbase, int dpat, char *dname)
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
** Input: node = a network junction node
|
||||||
|
** dbase = base demand value
|
||||||
|
** dpat = demand pattern index
|
||||||
|
** dname = name of demand category
|
||||||
|
** Output: returns TRUE if successful, FALSE if not
|
||||||
|
** Purpose: adds a new demand category to a node.
|
||||||
|
**----------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
Pdemand demand, lastdemand;
|
||||||
|
|
||||||
|
// Create a new demand struct
|
||||||
|
demand = (struct Sdemand *)malloc(sizeof(struct Sdemand));
|
||||||
|
if (demand == NULL) return FALSE;
|
||||||
|
|
||||||
|
// Assign it the designated properties
|
||||||
|
demand->Base = dbase;
|
||||||
|
demand->Pat = dpat;
|
||||||
|
demand->Name = NULL;
|
||||||
|
if (dname && strlen(dname) > 0) xstrcpy(&demand->Name, dname, MAXID);
|
||||||
|
demand->next = NULL;
|
||||||
|
|
||||||
|
// If node has no demands make this its first demand category
|
||||||
|
if (node->D == NULL) node->D = demand;
|
||||||
|
|
||||||
|
// Otherwise append this demand to the end of the node's demands list
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lastdemand = node->D;
|
||||||
|
while (lastdemand->next) lastdemand = lastdemand->next;
|
||||||
|
lastdemand->next = demand;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void freedemands(Snode *node)
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
** Input: node = a network junction node
|
||||||
|
** Output: node
|
||||||
|
** Purpose: frees the memory used for a node's list of demands.
|
||||||
|
**----------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
Pdemand nextdemand;
|
||||||
|
Pdemand demand = node->D;
|
||||||
|
while (demand != NULL)
|
||||||
|
{
|
||||||
|
nextdemand = demand->next;
|
||||||
|
free(demand->Name);
|
||||||
|
free(demand);
|
||||||
|
demand = nextdemand;
|
||||||
|
}
|
||||||
|
node->D = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int buildadjlists(Network *net)
|
int buildadjlists(Network *net)
|
||||||
/*
|
/*
|
||||||
@@ -790,16 +861,6 @@ void adjustpattern(int *pat, int index)
|
|||||||
else if (*pat > index) (*pat)--;
|
else if (*pat > index) (*pat)--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void adjust_demand_pattern(list_node_t *list_node, int deletion_index)
|
|
||||||
{
|
|
||||||
int pat_idx = get_pattern_index(list_node);
|
|
||||||
|
|
||||||
if (pat_idx == deletion_index) set_pattern_index(list_node, 0);
|
|
||||||
else if (pat_idx > deletion_index) set_pattern_index(list_node, --pat_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void adjustpatterns(Network *network, int index)
|
void adjustpatterns(Network *network, int index)
|
||||||
/*----------------------------------------------------------------
|
/*----------------------------------------------------------------
|
||||||
** Input: index = index of time pattern being deleted
|
** Input: index = index of time pattern being deleted
|
||||||
@@ -809,17 +870,16 @@ void adjustpatterns(Network *network, int index)
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
//Pdemand demand;
|
Pdemand demand;
|
||||||
Psource source;
|
Psource source;
|
||||||
|
|
||||||
// Adjust patterns used by junctions
|
// Adjust patterns used by junctions
|
||||||
for (j = 1; j <= network->Nnodes; j++)
|
for (j = 1; j <= network->Nnodes; j++)
|
||||||
{
|
{
|
||||||
// Adjust demand patterns
|
// Adjust demand patterns
|
||||||
list_t *dlist = network->Node[j].D;
|
for (demand = network->Node[j].D; demand != NULL; demand = demand->next)
|
||||||
if (dlist) {
|
{
|
||||||
for (list_node_t *lnode = first_list(dlist); done_list(lnode); lnode = next_list(lnode))
|
adjustpattern(&demand->Pat, index);
|
||||||
adjust_demand_pattern(lnode, index);
|
|
||||||
}
|
}
|
||||||
// Adjust WQ source patterns
|
// Adjust WQ source patterns
|
||||||
source = network->Node[j].S;
|
source = network->Node[j].S;
|
||||||
|
|||||||
21
src/types.h
21
src/types.h
@@ -16,9 +16,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "util/list.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
@@ -339,14 +337,14 @@ typedef struct // Curve Object
|
|||||||
double *Y; // y-values
|
double *Y; // y-values
|
||||||
} Scurve;
|
} Scurve;
|
||||||
|
|
||||||
//struct Sdemand // Demand List Item
|
struct Sdemand // Demand List Item
|
||||||
//{
|
{
|
||||||
// double Base; // baseline demand
|
double Base; // baseline demand
|
||||||
// int Pat; // pattern index
|
int Pat; // pattern index
|
||||||
// char *Name; // demand category name
|
char *Name; // demand category name
|
||||||
// struct Sdemand *next; // next demand list item
|
struct Sdemand *next; // next demand list item
|
||||||
//};
|
};
|
||||||
//typedef struct Sdemand *Pdemand; // Pointer to demand list
|
typedef struct Sdemand *Pdemand; // Pointer to demand list
|
||||||
|
|
||||||
typedef struct // Energy Usage Object
|
typedef struct // Energy Usage Object
|
||||||
{
|
{
|
||||||
@@ -373,8 +371,7 @@ typedef struct // Node Object
|
|||||||
double X; // x-coordinate
|
double X; // x-coordinate
|
||||||
double Y; // y-coordinate
|
double Y; // y-coordinate
|
||||||
double El; // elevation
|
double El; // elevation
|
||||||
// Pdemand D; // demand pointer
|
Pdemand D; // demand pointer
|
||||||
list_t *D; // pointer to demand list
|
|
||||||
Psource S; // source pointer
|
Psource S; // source pointer
|
||||||
double C0; // initial quality
|
double C0; // initial quality
|
||||||
double Ke; // emitter coeff.
|
double Ke; // emitter coeff.
|
||||||
|
|||||||
@@ -23,16 +23,6 @@ add_test(NAME test_net_builder
|
|||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data)
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data)
|
||||||
|
|
||||||
|
|
||||||
add_executable(test_demand_data test_demand_data.cpp
|
|
||||||
../src/demand.c
|
|
||||||
../src/util/list.c)
|
|
||||||
target_include_directories(test_demand_data PUBLIC ../src/ ../src/util/)
|
|
||||||
target_link_libraries(test_demand_data ${Boost_LIBRARIES} epanet2)
|
|
||||||
add_test(NAME test_demand_data
|
|
||||||
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_demand_data
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data)
|
|
||||||
|
|
||||||
|
|
||||||
set(toolkit_test_srcs
|
set(toolkit_test_srcs
|
||||||
test_toolkit.cpp
|
test_toolkit.cpp
|
||||||
test_project.cpp
|
test_project.cpp
|
||||||
@@ -81,6 +71,3 @@ add_test(NAME test_filemanager
|
|||||||
add_test(NAME test_output
|
add_test(NAME test_output
|
||||||
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_output
|
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_output
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/outfile/data)
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/outfile/data)
|
||||||
|
|
||||||
add_test(NAME test_list
|
|
||||||
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_list)
|
|
||||||
|
|||||||
@@ -84,31 +84,38 @@ BOOST_AUTO_TEST_CASE(test_categories_reopen, * boost::unit_test::depends_on("tes
|
|||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(test_adddemand, FixtureSingleNode)
|
BOOST_FIXTURE_TEST_CASE(test_adddemand, FixtureSingleNode)
|
||||||
{
|
{
|
||||||
int key, demand_key;
|
int Dindex, nD;
|
||||||
|
|
||||||
error = EN_adddemand(ph, node_qhut, 100.0, "PrimaryPattern", "PrimaryDemand", &demand_key);
|
error = EN_adddemand(ph, node_qhut, 100.0, "PrimaryPattern", "PrimaryDemand");
|
||||||
BOOST_CHECK(error != 0);
|
BOOST_CHECK(error != 0);
|
||||||
|
|
||||||
error = EN_addpattern(ph, (char *)"PrimaryPattern");
|
error = EN_addpattern(ph, (char *)"PrimaryPattern");
|
||||||
BOOST_REQUIRE(error == 0);
|
BOOST_REQUIRE(error == 0);
|
||||||
|
|
||||||
error = EN_adddemand(ph, node_qhut, 100.0, "PrimaryPattern", "PrimaryDemand", &demand_key);
|
error = EN_adddemand(ph, node_qhut, 100.0, "PrimaryPattern", "PrimaryDemand");
|
||||||
BOOST_CHECK(error == 0);
|
BOOST_CHECK(error == 0);
|
||||||
|
|
||||||
error = EN_addpattern(ph, (char *)"SecondaryPattern");
|
error = EN_addpattern(ph, (char *)"SecondaryPattern");
|
||||||
BOOST_REQUIRE(error == 0);
|
BOOST_REQUIRE(error == 0);
|
||||||
|
|
||||||
error = EN_adddemand(ph, node_qhut, 10.0, "SecondaryPattern", "SecondaryDemand", &key);
|
error = EN_adddemand(ph, node_qhut, 10.0, "SecondaryPattern", "SecondaryDemand");
|
||||||
BOOST_CHECK(error == 0);
|
BOOST_CHECK(error == 0);
|
||||||
|
|
||||||
error = EN_addpattern(ph, (char *)"TertiaryPattern");
|
error = EN_addpattern(ph, (char *)"TertiaryPattern");
|
||||||
BOOST_REQUIRE(error == 0);
|
BOOST_REQUIRE(error == 0);
|
||||||
|
|
||||||
error = EN_adddemand(ph, node_qhut, 1.0, "TertiaryPattern", "TertiaryDemand", &demand_key);
|
error = EN_adddemand(ph, node_qhut, 1.0, "TertiaryPattern", "TertiaryDemand");
|
||||||
|
BOOST_CHECK(error == 0);
|
||||||
|
|
||||||
|
error = EN_getdemandindex(ph, node_qhut, "TertiaryDemand", &Dindex);
|
||||||
BOOST_CHECK(error == 0);
|
BOOST_CHECK(error == 0);
|
||||||
|
|
||||||
error = EN_removedemand(ph, node_qhut, key);
|
error = EN_deletedemand(ph, node_qhut, Dindex);
|
||||||
BOOST_CHECK(error == 0);
|
BOOST_CHECK(error == 0);
|
||||||
|
|
||||||
|
error = EN_getnumdemands(ph, node_qhut, &nD);
|
||||||
|
BOOST_REQUIRE(error == 0);
|
||||||
|
BOOST_CHECK(nD == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,295 +0,0 @@
|
|||||||
/*
|
|
||||||
******************************************************************************
|
|
||||||
Project: OWA EPANET
|
|
||||||
Version: 2.2
|
|
||||||
Module: /test_demand_data.cpp
|
|
||||||
Description: tests demand data list node struct
|
|
||||||
Authors: see AUTHORS
|
|
||||||
Copyright: see AUTHORS
|
|
||||||
License: see LICENSE
|
|
||||||
Last Updated: 04/18/2019
|
|
||||||
******************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define BOOST_TEST_MODULE demand_data
|
|
||||||
#include <boost/test/unit_test.hpp>
|
|
||||||
|
|
||||||
#include "demand.h"
|
|
||||||
#include "epanet2_2.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define DATA_PATH_NET1 "./net1.inp"
|
|
||||||
#define DATA_PATH_TMP "./tmp.inp"
|
|
||||||
#define DATA_PATH_RPT "./test.rpt"
|
|
||||||
#define DATA_PATH_OUT "./test.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_demand_data)
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_create_destroy_demand_list)
|
|
||||||
{
|
|
||||||
list_t *dlist;
|
|
||||||
|
|
||||||
dlist = create_demand_list(100.0, 1, "CUB_SCOUT_DAY_CAMP");
|
|
||||||
BOOST_CHECK(dlist != NULL);
|
|
||||||
|
|
||||||
delete_list(dlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE (test_create_destroy)
|
|
||||||
{
|
|
||||||
void *data = NULL;
|
|
||||||
|
|
||||||
data = create_demand_data(100.0, 1, NULL);
|
|
||||||
BOOST_CHECK(data != NULL);
|
|
||||||
|
|
||||||
delete_demand_data(&data);
|
|
||||||
|
|
||||||
data = NULL;
|
|
||||||
|
|
||||||
data = create_demand_data(100.0, 1, "CUB_SCOUT_BASE_CAMP");
|
|
||||||
BOOST_CHECK(data != NULL);
|
|
||||||
|
|
||||||
delete_demand_data(&data);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_get_size)
|
|
||||||
{
|
|
||||||
size_t size = get_demand_data_size();
|
|
||||||
BOOST_CHECK(size == sizeof(demand_data_t *));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct Fixture {
|
|
||||||
Fixture() {
|
|
||||||
_data = NULL;
|
|
||||||
dlist = NULL;
|
|
||||||
|
|
||||||
dlist = create_list(get_demand_data_size(), delete_demand_data);
|
|
||||||
_data = create_demand_data(100.0, 1, "CUB_SCOUT_BASE_CAMP");
|
|
||||||
|
|
||||||
append_list(dlist, &_data);
|
|
||||||
}
|
|
||||||
~Fixture() {
|
|
||||||
delete_list(dlist);
|
|
||||||
}
|
|
||||||
demand_data_t *_data;
|
|
||||||
list_t *dlist;
|
|
||||||
};
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(test_demand_list, Fixture)
|
|
||||||
{
|
|
||||||
list_node_t *lnode = head_list(dlist, false);
|
|
||||||
BOOST_CHECK(lnode != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(test_demand_getset, Fixture)
|
|
||||||
{
|
|
||||||
list_node_t *lnode = head_list(dlist, false);
|
|
||||||
double demand;
|
|
||||||
|
|
||||||
demand = get_base_demand(lnode);
|
|
||||||
BOOST_CHECK(demand == 100.0);
|
|
||||||
|
|
||||||
set_base_demand(lnode, 200.0);
|
|
||||||
|
|
||||||
demand = get_base_demand(lnode);
|
|
||||||
BOOST_CHECK(demand == 200.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(test_pattern_getset, Fixture)
|
|
||||||
{
|
|
||||||
list_node_t *lnode = head_list(dlist, false);
|
|
||||||
int index;
|
|
||||||
|
|
||||||
index = get_pattern_index(lnode);
|
|
||||||
BOOST_CHECK(index == 1);
|
|
||||||
|
|
||||||
set_pattern_index(lnode, 2);
|
|
||||||
|
|
||||||
index = get_pattern_index(lnode);
|
|
||||||
BOOST_CHECK(index == 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(test_category_getset, Fixture)
|
|
||||||
{
|
|
||||||
list_node_t *lnode = head_list(dlist, false);
|
|
||||||
char *name = NULL;
|
|
||||||
|
|
||||||
name = get_category_name(lnode);
|
|
||||||
BOOST_CHECK(check_string(name, (char *)"CUB_SCOUT_BASE_CAMP"));
|
|
||||||
|
|
||||||
free(name);
|
|
||||||
name = NULL;
|
|
||||||
|
|
||||||
set_category_name(lnode, (char *)"CUB_SCOUT_COMMAND");
|
|
||||||
|
|
||||||
name = get_category_name(lnode);
|
|
||||||
BOOST_CHECK(check_string(name, "CUB_SCOUT_COMMAND"));
|
|
||||||
|
|
||||||
free(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(test_convert_demand, Fixture)
|
|
||||||
{
|
|
||||||
list_node_t *lnode = head_list(dlist, false);
|
|
||||||
BOOST_CHECK(lnode != NULL);
|
|
||||||
|
|
||||||
// 100.0 GPM == 6.31 LPS
|
|
||||||
convert_units(lnode, 15.850);
|
|
||||||
double demand = get_base_demand(lnode);
|
|
||||||
BOOST_TEST(demand == 6.31, boost::test_tools::tolerance(0.01));
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_initclose)
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
|
|
||||||
EN_Project ph = NULL;
|
|
||||||
|
|
||||||
EN_createproject(&ph);
|
|
||||||
|
|
||||||
error = EN_init(ph, DATA_PATH_RPT, DATA_PATH_OUT, EN_GPM, EN_HW);
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
|
|
||||||
error = EN_close(ph);
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
|
|
||||||
EN_deleteproject(&ph);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define DATA_PATH_NET1 "./net1.inp"
|
|
||||||
#define DATA_PATH_TMP "./tmp.inp"
|
|
||||||
#define DATA_PATH_RPT "./test.rpt"
|
|
||||||
#define DATA_PATH_OUT "./test.out"
|
|
||||||
|
|
||||||
|
|
||||||
struct FixtureSingleNode {
|
|
||||||
FixtureSingleNode() {
|
|
||||||
error = 0;
|
|
||||||
ph = NULL;
|
|
||||||
|
|
||||||
EN_createproject(&ph);
|
|
||||||
EN_init(ph, DATA_PATH_RPT, DATA_PATH_OUT, EN_GPM, EN_HW);
|
|
||||||
|
|
||||||
EN_addnode(ph, (char *)"CUB_SCOUT_QUONSET_HUT", EN_JUNCTION, &node_qhut);
|
|
||||||
//EN_getnodeindex(ph, (char *)"CUB_SCOUT_QUONSET_HUT", &node_qhut);
|
|
||||||
}
|
|
||||||
|
|
||||||
~FixtureSingleNode() {
|
|
||||||
EN_close(ph);
|
|
||||||
EN_deleteproject(&ph);
|
|
||||||
}
|
|
||||||
int error, index, node_qhut;
|
|
||||||
EN_Project ph;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(test_single_node, FixtureSingleNode)
|
|
||||||
{
|
|
||||||
int demand_idx, pattern_idx, n;
|
|
||||||
double demand;
|
|
||||||
|
|
||||||
error = EN_getnumdemands(ph, node_qhut, &n);
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
BOOST_CHECK(n == 0);
|
|
||||||
|
|
||||||
demand_idx = 1;
|
|
||||||
error = EN_getbasedemand(ph, node_qhut, demand_idx, &demand);
|
|
||||||
BOOST_REQUIRE(error == 253);
|
|
||||||
|
|
||||||
error = EN_getdemandpattern(ph, node_qhut, demand_idx, &pattern_idx);
|
|
||||||
BOOST_REQUIRE(error == 253);
|
|
||||||
|
|
||||||
char demname[31];
|
|
||||||
error = EN_getdemandname(ph, node_qhut, demand_idx, demname);
|
|
||||||
BOOST_REQUIRE(error == 253);
|
|
||||||
BOOST_CHECK(check_string(demname, "\0"));
|
|
||||||
|
|
||||||
error = EN_setbasedemand(ph, node_qhut, demand_idx, 100.0);
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
|
|
||||||
// only one demand category
|
|
||||||
pattern_idx = 1;
|
|
||||||
error = EN_setdemandpattern(ph, node_qhut, demand_idx, pattern_idx);
|
|
||||||
BOOST_REQUIRE(error == 205);
|
|
||||||
|
|
||||||
// create pattern
|
|
||||||
error = EN_addpattern(ph, (char *)"Pat2");
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
error = EN_getpatternindex(ph, (char *)"Pat2", &pattern_idx);
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
|
|
||||||
error = EN_setdemandpattern(ph, node_qhut, demand_idx, pattern_idx);
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
|
|
||||||
error = EN_setdemandname(ph, node_qhut, demand_idx, (char *)"CUB_SCOUT_MESS_HALL");
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(test_pattern_edits, FixtureSingleNode)
|
|
||||||
{
|
|
||||||
int n, node_cpoint, pat2_idx, pat3_idx;
|
|
||||||
|
|
||||||
EN_addnode(ph, (char *)"CUB_SCOUT_CHECKPOINT", EN_JUNCTION, &node_cpoint);
|
|
||||||
//EN_getnodeindex(ph, (char *)"CUB_SCOUT_CHECKPOINT", &node_cpoint);
|
|
||||||
|
|
||||||
// Add 2 new patterns
|
|
||||||
error = EN_addpattern(ph, (char *)"DefPat");
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
error = EN_addpattern(ph, (char *)"Pat2");
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
error = EN_getpatternindex(ph, (char *)"Pat2", &pat2_idx);
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
|
|
||||||
error = EN_addpattern(ph, (char *)"Pat3");
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
error = EN_getpatternindex(ph, (char *)"Pat3", &pat3_idx);
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
|
|
||||||
double f2[] = { 2.1, 2.2 };
|
|
||||||
double f3[] = { 3.1, 3.2, 3.3, 3.4 };
|
|
||||||
error = EN_setpattern(ph, pat2_idx, f2, 2);
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
error = EN_setpattern(ph, pat3_idx, f3, 4);
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
|
|
||||||
// Assign Pat3 to 3rd junction
|
|
||||||
error = EN_setdemandpattern(ph, node_cpoint, 1, pat3_idx);
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
|
|
||||||
// Delete Pat2
|
|
||||||
error = EN_deletepattern(ph, pat2_idx);
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
|
|
||||||
//Check that there are now 2 patterns
|
|
||||||
error = EN_getcount(ph, EN_PATCOUNT, &n);
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
BOOST_CHECK(n == 2);
|
|
||||||
|
|
||||||
// Check that Pat3 with 4 factors is still assigned to 3rd junction
|
|
||||||
error = EN_getdemandpattern(ph, node_cpoint, 1, &pat3_idx);
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
error = EN_getpatternlen(ph, pat3_idx, &n);
|
|
||||||
BOOST_REQUIRE(error == 0);
|
|
||||||
BOOST_CHECK(n == 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
|
||||||
@@ -25,8 +25,3 @@ add_executable(test_filemanager ./test_filemanager.cpp
|
|||||||
target_include_directories(test_filemanager PUBLIC ../../src/)
|
target_include_directories(test_filemanager PUBLIC ../../src/)
|
||||||
target_link_libraries(test_filemanager ${Boost_LIBRARIES})
|
target_link_libraries(test_filemanager ${Boost_LIBRARIES})
|
||||||
|
|
||||||
|
|
||||||
add_executable(test_list ./test_list.cpp
|
|
||||||
../../src/util/list.c)
|
|
||||||
target_include_directories(test_list PUBLIC ../../src/)
|
|
||||||
target_link_libraries(test_list ${Boost_LIBRARIES})
|
|
||||||
|
|||||||
@@ -1,248 +0,0 @@
|
|||||||
/*
|
|
||||||
******************************************************************************
|
|
||||||
Project: OWA EPANET
|
|
||||||
Version: 2.2
|
|
||||||
Module: util/list.h
|
|
||||||
Description: Generic list
|
|
||||||
https://gist.github.com/pseudomuto/6334796#file-sample_app-c
|
|
||||||
Accessed: April 9, 2019
|
|
||||||
Authors: David Muto, Modified by Michael E. Tryby
|
|
||||||
Copyright: see AUTHORS
|
|
||||||
License: see LICENSE
|
|
||||||
Last Updated: 04/09/2019
|
|
||||||
******************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#define BOOST_TEST_MODULE list
|
|
||||||
#include <boost/test/unit_test.hpp>
|
|
||||||
|
|
||||||
#include "util/list.h"
|
|
||||||
|
|
||||||
|
|
||||||
boost::test_tools::predicate_result check_string(std::string test, std::string ref)
|
|
||||||
{
|
|
||||||
if (ref.compare(test) == 0)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int *get_int_data(list_node_t *lnode) {
|
|
||||||
return (int *)get_data(lnode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iterate_int(list_node_t *lnode)
|
|
||||||
{
|
|
||||||
printf("At Key: %d Found value: %d\n", get_key(lnode), *get_int_data(lnode));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE(test_list)
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_create_delete) {
|
|
||||||
|
|
||||||
list_t *list;
|
|
||||||
list = create_list(sizeof(int), NULL);
|
|
||||||
|
|
||||||
delete_list(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_int_list){
|
|
||||||
|
|
||||||
int i, numbers = 10;
|
|
||||||
list_t *list = NULL;
|
|
||||||
|
|
||||||
int key[10 + 1];
|
|
||||||
|
|
||||||
srand((unsigned int)time(0));
|
|
||||||
|
|
||||||
list = create_list(sizeof(int), NULL);
|
|
||||||
|
|
||||||
for(i = 1; i <= numbers; i++) {
|
|
||||||
key[i] = append_list(list, &i);
|
|
||||||
}
|
|
||||||
BOOST_CHECK(size_list(list) == 10);
|
|
||||||
|
|
||||||
listIterator iterator = (listIterator)iterate_int;
|
|
||||||
for_each_list(list, iterator);
|
|
||||||
|
|
||||||
list_node_t *lnode = search_list(list, key[5]);
|
|
||||||
BOOST_CHECK(get_key(lnode) == key[5]);
|
|
||||||
|
|
||||||
delete_list(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline char *get_string_data(list_node_t *lnode)
|
|
||||||
{
|
|
||||||
return *(char **)get_data(lnode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iterate_string(list_node_t *lnode)
|
|
||||||
{
|
|
||||||
printf("Found string value: %s\n", get_string_data(lnode));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void free_string(void *data)
|
|
||||||
{
|
|
||||||
free(*(char **)data);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FixtureStrings{
|
|
||||||
FixtureStrings() {
|
|
||||||
list = NULL;
|
|
||||||
|
|
||||||
int numNames = 5;
|
|
||||||
const char *names[] = { "David", "Kevin", "Michael", "Craig", "Jimi" };
|
|
||||||
|
|
||||||
list = create_list(sizeof(char *), free_string);
|
|
||||||
|
|
||||||
char *name;
|
|
||||||
for (int i = 0; i < numNames; i++) {
|
|
||||||
name = strdup(names[i]);
|
|
||||||
append_list(list, &name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
~FixtureStrings() {
|
|
||||||
delete_list(list);
|
|
||||||
}
|
|
||||||
list_t *list;
|
|
||||||
};
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(test_string_list, FixtureStrings) {
|
|
||||||
|
|
||||||
BOOST_CHECK(size_list(list) == 5);
|
|
||||||
|
|
||||||
listIterator iterator = (listIterator)iterate_string;
|
|
||||||
for_each_list(list, iterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(test_head_list, FixtureStrings) {
|
|
||||||
|
|
||||||
BOOST_CHECK(check_string(get_string_data(head_list(list, false)), "David"));
|
|
||||||
BOOST_CHECK(size_list(list) == 5);
|
|
||||||
|
|
||||||
list_node_t *lnode = head_list(list, true);
|
|
||||||
BOOST_CHECK(check_string(get_string_data(lnode), "David"));
|
|
||||||
delete_node(list, lnode);
|
|
||||||
|
|
||||||
BOOST_CHECK(check_string(get_string_data(head_list(list, false)), "Kevin"));
|
|
||||||
BOOST_CHECK(size_list(list) == 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(test_tail_list, FixtureStrings) {
|
|
||||||
|
|
||||||
BOOST_CHECK(check_string(get_string_data(tail_list(list)), "Jimi"));
|
|
||||||
BOOST_CHECK(size_list(list) == 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct test_data_s {
|
|
||||||
int num;
|
|
||||||
char *name;
|
|
||||||
} test_data_t;
|
|
||||||
|
|
||||||
test_data_t *create_test_data(int number, const char *name){
|
|
||||||
|
|
||||||
test_data_t *data = (test_data_t *)malloc(sizeof(test_data_t));
|
|
||||||
data->num = number;
|
|
||||||
if (name)
|
|
||||||
data->name = strdup(name);
|
|
||||||
else
|
|
||||||
data->name = NULL;
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void delete_test_data(void *data) {
|
|
||||||
|
|
||||||
test_data_t *test_data = *(test_data_t **)data;
|
|
||||||
|
|
||||||
if (test_data->name)
|
|
||||||
free(test_data->name);
|
|
||||||
|
|
||||||
free(test_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline test_data_t *get_test_data(list_node_t *lnode)
|
|
||||||
{
|
|
||||||
return *(test_data_t **)get_data(lnode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iterate_test_data(list_node_t *lnode)
|
|
||||||
{
|
|
||||||
test_data_t *test_data = get_test_data(lnode);
|
|
||||||
|
|
||||||
printf("Found number: %i name: %s\n", test_data->num, test_data->name);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char *get_name(list_node_t *lnode)
|
|
||||||
{
|
|
||||||
return get_test_data(lnode)->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_struct_list){
|
|
||||||
|
|
||||||
int key, head_key, tail_key;
|
|
||||||
|
|
||||||
list_t *list = NULL;
|
|
||||||
list = create_list(sizeof(test_data_t *), delete_test_data);
|
|
||||||
|
|
||||||
|
|
||||||
test_data_t *data = create_test_data(1, "David");
|
|
||||||
head_key = append_list(list, &data);
|
|
||||||
|
|
||||||
data = create_test_data(2, "Kevin");
|
|
||||||
key = append_list(list, &data);
|
|
||||||
|
|
||||||
data = create_test_data(3, "Michael");
|
|
||||||
append_list(list, &data);
|
|
||||||
|
|
||||||
data = create_test_data(4, "Craig");
|
|
||||||
append_list(list, &data);
|
|
||||||
|
|
||||||
data = create_test_data(5, "Jimi");
|
|
||||||
tail_key = append_list(list, &data);
|
|
||||||
|
|
||||||
BOOST_CHECK(size_list(list) == 5);
|
|
||||||
|
|
||||||
listIterator iterator = (listIterator)iterate_test_data;
|
|
||||||
for_each_list(list, iterator);
|
|
||||||
|
|
||||||
|
|
||||||
// locate a list node by a key
|
|
||||||
printf("Found %s!\n", get_name(search_list(list, key)));
|
|
||||||
|
|
||||||
printf("Removing Kevin\n");
|
|
||||||
remove_node(list, key);
|
|
||||||
for_each_list(list, iterator);
|
|
||||||
|
|
||||||
printf("Removing David\n");
|
|
||||||
remove_node(list, head_key);
|
|
||||||
for_each_list(list, iterator);
|
|
||||||
|
|
||||||
printf("Removing Jimi\n");
|
|
||||||
remove_node(list, tail_key);
|
|
||||||
for_each_list(list, iterator);
|
|
||||||
|
|
||||||
list_node_t *lnode = head_list(list, true);
|
|
||||||
delete_node(list, lnode);
|
|
||||||
|
|
||||||
delete_list(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: search for an index and return data
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
|
||||||
@@ -5,6 +5,7 @@ EXPORTS
|
|||||||
ENaddcurve = _ENaddcurve@4
|
ENaddcurve = _ENaddcurve@4
|
||||||
ENaddlink = _ENaddlink@20
|
ENaddlink = _ENaddlink@20
|
||||||
ENaddnode = _ENaddnode@12
|
ENaddnode = _ENaddnode@12
|
||||||
|
ENadddemand = _ENadddemand@16
|
||||||
ENaddpattern = _ENaddpattern@4
|
ENaddpattern = _ENaddpattern@4
|
||||||
ENaddrule = _ENaddrule@4
|
ENaddrule = _ENaddrule@4
|
||||||
ENclearreport = _ENclearreport@0
|
ENclearreport = _ENclearreport@0
|
||||||
@@ -14,6 +15,7 @@ EXPORTS
|
|||||||
ENcopyreport = _ENcopyreport@4
|
ENcopyreport = _ENcopyreport@4
|
||||||
ENdeletecontrol = _ENdeletecontrol@4
|
ENdeletecontrol = _ENdeletecontrol@4
|
||||||
ENdeletecurve = _ENdeletecurve@4
|
ENdeletecurve = _ENdeletecurve@4
|
||||||
|
ENdeletedemand = _ENdeletedemand@8
|
||||||
ENdeletelink = _ENdeletelink@8
|
ENdeletelink = _ENdeletelink@8
|
||||||
ENdeletenode = _ENdeletenode@8
|
ENdeletenode = _ENdeletenode@8
|
||||||
ENdeletepattern = _ENdeletepattern@4
|
ENdeletepattern = _ENdeletepattern@4
|
||||||
@@ -30,7 +32,8 @@ EXPORTS
|
|||||||
ENgetcurveindex = _ENgetcurveindex@8
|
ENgetcurveindex = _ENgetcurveindex@8
|
||||||
ENgetcurvelen = _ENgetcurvelen@8
|
ENgetcurvelen = _ENgetcurvelen@8
|
||||||
ENgetcurvetype = _ENgetcurvetype@8
|
ENgetcurvetype = _ENgetcurvetype@8
|
||||||
ENgetcurvevalue = _ENgetcurvevalue@16
|
ENgetcurvevalue = _ENgetcurvevalue@16
|
||||||
|
ENgetdemandindex = _ENgetdemandindex@12
|
||||||
ENgetdemandmodel = _ENgetdemandmodel@16
|
ENgetdemandmodel = _ENgetdemandmodel@16
|
||||||
ENgetdemandname = _ENgetdemandname@12
|
ENgetdemandname = _ENgetdemandname@12
|
||||||
ENgetdemandpattern = _ENgetdemandpattern@12
|
ENgetdemandpattern = _ENgetdemandpattern@12
|
||||||
|
|||||||
Reference in New Issue
Block a user