Work in progress
code cleanup, addressed issue raised in review, and implemented EN_adddemand()
This commit is contained in:
@@ -165,7 +165,7 @@ typedef struct Project *EN_Project;
|
||||
@return an error code
|
||||
*/
|
||||
int DLLEXPORT EN_setcomment(EN_Project ph, int object, int index, char *comment);
|
||||
|
||||
|
||||
/**
|
||||
@brief Retrieves the number of objects of a given type in a project.
|
||||
@param ph an EPANET project handle.
|
||||
@@ -851,7 +851,14 @@ typedef struct Project *EN_Project;
|
||||
These properties have units that depend on the units used for flow rate (see @ref Units).
|
||||
*/
|
||||
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.
|
||||
|
||||
83
src/epanet.c
83
src/epanet.c
@@ -1888,15 +1888,9 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode)
|
||||
|
||||
// Free memory allocated to node's demands, WQ source & comment
|
||||
demand = node->D;
|
||||
if (demand)
|
||||
delete_list(demand);
|
||||
// while (demand != NULL)
|
||||
// {
|
||||
// nextdemand = demand->next;
|
||||
// free(demand->Name);
|
||||
// free(demand);
|
||||
// demand = nextdemand;
|
||||
// }
|
||||
if (demand)
|
||||
delete_list(demand);
|
||||
|
||||
free(node->S);
|
||||
free(node->Comment);
|
||||
|
||||
@@ -2063,7 +2057,6 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val
|
||||
Quality *qual = &p->quality;
|
||||
|
||||
double v = 0.0;
|
||||
//Pdemand demand;
|
||||
Psource source;
|
||||
|
||||
Snode *Node = net->Node;
|
||||
@@ -2090,17 +2083,12 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val
|
||||
|
||||
case EN_BASEDEMAND:
|
||||
v = 0.0;
|
||||
// NOTE: primary demand category is last on demand list
|
||||
// NOTE: primary demand category is first on demand list
|
||||
if (index <= nJuncs)
|
||||
{
|
||||
list_t *demand = Node[index].D;
|
||||
if (demand)
|
||||
v = get_base_demand(tail_list(demand));
|
||||
|
||||
//for (demand = Node[index].D; demand != NULL; demand = demand->next)
|
||||
//{
|
||||
// v = (demand->Base);
|
||||
//}
|
||||
list_t *demand = Node[index].D;
|
||||
if (demand)
|
||||
v = get_base_demand(head_list(demand, false));
|
||||
}
|
||||
v *= Ucf[FLOW];
|
||||
break;
|
||||
@@ -2110,9 +2098,9 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val
|
||||
// NOTE: primary demand category is first on demand list
|
||||
if (index <= nJuncs)
|
||||
{
|
||||
list_t *demand = Node[index].D;
|
||||
if (demand)
|
||||
v = get_pattern_index(head_list(demand, false));
|
||||
list_t *demand = Node[index].D;
|
||||
if (demand)
|
||||
v = get_pattern_index(head_list(demand, false));
|
||||
}
|
||||
else v = (double)(Tank[index - nJuncs].Pat);
|
||||
break;
|
||||
@@ -2267,7 +2255,6 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
||||
double *Ucf = p->Ucf;
|
||||
|
||||
int i, j, n;
|
||||
// Pdemand demand;
|
||||
Psource source;
|
||||
double hTmp;
|
||||
|
||||
@@ -2293,9 +2280,9 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu
|
||||
// NOTE: primary demand category is first on demand list
|
||||
if (index <= nJuncs)
|
||||
{
|
||||
list_t *demand = Node[index].D;
|
||||
if (demand)
|
||||
set_base_demand(head_list(demand, false), value / Ucf[FLOW]);
|
||||
list_t *demand = Node[index].D;
|
||||
if (demand)
|
||||
set_base_demand(head_list(demand, false), value / Ucf[FLOW]);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2504,7 +2491,6 @@ int DLLEXPORT EN_setjuncdata(EN_Project p, int index, double elev,
|
||||
|
||||
int i, patIndex = 0;
|
||||
Snode *Node = net->Node;
|
||||
//Pdemand demand;
|
||||
|
||||
// Check that junction exists
|
||||
if (!p->Openflag) return 102;
|
||||
@@ -2532,7 +2518,7 @@ int DLLEXPORT EN_setjuncdata(EN_Project p, int index, double elev,
|
||||
demand_list = create_list(get_demand_data_size(), delete_demand_data);
|
||||
if (!demand_list) return 101;
|
||||
}
|
||||
demand_data_t *demand_data = create_demand_data(dmnd / p->Ucf[FLOW], patIndex, NULL);
|
||||
demand_data_t *demand_data = create_demand_data(dmnd/p->Ucf[FLOW], patIndex, NULL);
|
||||
if (!demand_data) return 101;
|
||||
|
||||
append_list(demand_list, &demand_data);
|
||||
@@ -2540,6 +2526,47 @@ int DLLEXPORT EN_setjuncdata(EN_Project p, int index, double elev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DLLEXPORT EN_adddemand(EN_Project p, int node_index, double demand,
|
||||
char *demand_pattern, const char *category_name, int *demand_index)
|
||||
{
|
||||
Network *net = &p->network;
|
||||
|
||||
int pattern_index, error = 0;
|
||||
*demand_index = -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;
|
||||
|
||||
append_list(demand_list, &demand_data);
|
||||
}
|
||||
|
||||
*demand_index = size_list(demand_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DLLEXPORT EN_removedemand(EN_Project p, int node_index, int demand_index) {
|
||||
// Problem: Removing a demand will in most cases invalidate the index
|
||||
// returned previously in EN_adddemand(). This occurs in all cases except
|
||||
// when the demand at the tail of the list is removed. This is why indexing
|
||||
// is a flawed strategy for random access to a list data structure.
|
||||
// One possible solution is to have the user be responsible for creating a
|
||||
// unique category name. Another possible solution would be for the
|
||||
// application to create a unique key for each demand entry. They have
|
||||
// random access based on searching for a key value in the list.
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DLLEXPORT EN_settankdata(EN_Project p, int index, double elev,
|
||||
double initlvl, double minlvl,
|
||||
double maxlvl, double diam,
|
||||
|
||||
@@ -791,12 +791,12 @@ void adjustpattern(int *pat, int index)
|
||||
}
|
||||
|
||||
|
||||
void adjust_demand_pattern(list_node_t *lnode, int del_idx)
|
||||
void adjust_demand_pattern(list_node_t *list_node, int deletion_index)
|
||||
{
|
||||
int pat_idx = get_pattern_index(lnode);
|
||||
int pat_idx = get_pattern_index(list_node);
|
||||
|
||||
if (pat_idx == del_idx) set_pattern_index(lnode, 0);
|
||||
else if (pat_idx > del_idx) set_pattern_index(lnode, --pat_idx);
|
||||
if (pat_idx == deletion_index) set_pattern_index(list_node, 0);
|
||||
else if (pat_idx > deletion_index) set_pattern_index(list_node, --pat_idx);
|
||||
}
|
||||
|
||||
|
||||
@@ -816,11 +816,11 @@ void adjustpatterns(Network *network, int index)
|
||||
for (j = 1; j <= network->Nnodes; j++)
|
||||
{
|
||||
// Adjust demand patterns
|
||||
list_t *dlist = network->Node[j].D;
|
||||
if (dlist) {
|
||||
for (list_node_t *lnode = first_list(dlist); done_list(lnode); lnode = next_list(lnode))
|
||||
adjust_demand_pattern(lnode, index);
|
||||
}
|
||||
list_t *dlist = network->Node[j].D;
|
||||
if (dlist) {
|
||||
for (list_node_t *lnode = first_list(dlist); done_list(lnode); lnode = next_list(lnode))
|
||||
adjust_demand_pattern(lnode, index);
|
||||
}
|
||||
// Adjust WQ source patterns
|
||||
source = network->Node[j].S;
|
||||
if (source) adjustpattern(&source->Pat, index);
|
||||
|
||||
@@ -82,5 +82,19 @@ BOOST_AUTO_TEST_CASE(test_categories_reopen, * boost::unit_test::depends_on("tes
|
||||
BOOST_REQUIRE(error == 0);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_adddemand, FixtureSingleNode)
|
||||
{
|
||||
int demand_index;
|
||||
|
||||
error = EN_adddemand(ph, node_qhut, 100.0, "PrimaryPattern", "PrimaryDemand", &demand_index);
|
||||
BOOST_CHECK(error != 0);
|
||||
|
||||
error = EN_addpattern(ph, (char *)"PrimaryPattern");
|
||||
BOOST_REQUIRE(error == 0);
|
||||
|
||||
error = EN_adddemand(ph, node_qhut, 100.0, "PrimaryPattern", "PrimaryDemand", &demand_index);
|
||||
BOOST_CHECK(error == 0);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
@@ -291,4 +291,5 @@ BOOST_FIXTURE_TEST_CASE(test_pattern_edits, FixtureSingleNode)
|
||||
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
@@ -102,6 +102,26 @@ struct FixtureAfterStep{
|
||||
EN_Project ph;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
~FixtureSingleNode() {
|
||||
EN_close(ph);
|
||||
EN_deleteproject(&ph);
|
||||
}
|
||||
int error, index, node_qhut;
|
||||
EN_Project ph;
|
||||
};
|
||||
|
||||
|
||||
boost::test_tools::predicate_result check_cdd_double(std::vector<double>& test,
|
||||
std::vector<double>& ref, long cdd_tol);
|
||||
boost::test_tools::predicate_result check_string(std::string test, std::string ref);
|
||||
|
||||
Reference in New Issue
Block a user