187 lines
5.5 KiB
C
187 lines
5.5 KiB
C
/*
|
|
******************************************************************************
|
|
Project: OWA EPANET
|
|
Version: 2.3
|
|
Module: flowbalance.c
|
|
Description: computes components of network's flow balance
|
|
Authors: see AUTHORS
|
|
Copyright: see AUTHORS
|
|
License: see LICENSE
|
|
Last Updated: 06/26/2024
|
|
******************************************************************************
|
|
*/
|
|
|
|
#include "types.h"
|
|
|
|
// Exported functions (declared in funcs.h)
|
|
//void startflowbalance(Project *);
|
|
//void updateflowbalance(Project *, long);
|
|
//void endflowbalance(Project *);
|
|
|
|
void startflowbalance(Project *pr)
|
|
/*
|
|
**-------------------------------------------------------------------
|
|
** Input: none
|
|
** Output: none
|
|
** Purpose: initializes components of the network's flow balance.
|
|
**-------------------------------------------------------------------
|
|
*/
|
|
{
|
|
Hydraul *hyd = &pr->hydraul;
|
|
hyd->FlowBalance.totalInflow = 0.0;
|
|
hyd->FlowBalance.totalOutflow = 0.0;
|
|
hyd->FlowBalance.consumerDemand = 0.0;
|
|
hyd->FlowBalance.emitterDemand = 0.0;
|
|
hyd->FlowBalance.leakageDemand = 0.0;
|
|
hyd->FlowBalance.deficitDemand = 0.0;
|
|
hyd->FlowBalance.storageDemand = 0.0;
|
|
hyd->FlowBalance.ratio = 0.0;
|
|
}
|
|
|
|
void updateflowbalance(Project *pr, long hstep)
|
|
/*
|
|
**-------------------------------------------------------------------
|
|
** Input: hstep = time step (sec)
|
|
** Output: none
|
|
** Purpose: updates components of the system flow balance.
|
|
**-------------------------------------------------------------------
|
|
*/
|
|
{
|
|
Network *net = &pr->network;
|
|
Hydraul *hyd = &pr->hydraul;
|
|
Times *time = &pr->times;
|
|
|
|
int i, j;
|
|
double v, dt, deficit, fullDemand;
|
|
SflowBalance flowBalance;
|
|
|
|
// Determine current time interval in seconds
|
|
if (time->Dur == 0) dt = 1.0;
|
|
else if (time->Htime < time->Dur)
|
|
{
|
|
dt = (double) hstep;
|
|
}
|
|
else return;
|
|
|
|
// Initialize local flow balance
|
|
flowBalance.totalInflow = 0.0;
|
|
flowBalance.totalOutflow = 0.0;
|
|
flowBalance.consumerDemand = 0.0;
|
|
flowBalance.emitterDemand = 0.0;
|
|
flowBalance.leakageDemand = 0.0;
|
|
flowBalance.deficitDemand = 0.0;
|
|
flowBalance.storageDemand = 0.0;
|
|
fullDemand = 0.0;
|
|
|
|
// Initialize leakage loss
|
|
hyd->LeakageLoss = 0.0;
|
|
|
|
// Examine each junction node
|
|
for (i = 1; i <= net->Njuncs; i++)
|
|
{
|
|
// Accumulate consumer demand flow
|
|
v = hyd->DemandFlow[i];
|
|
if (v < 0.0)
|
|
flowBalance.totalInflow += (-v);
|
|
else
|
|
{
|
|
fullDemand += hyd->FullDemand[i];
|
|
flowBalance.consumerDemand += v;
|
|
flowBalance.totalOutflow += v;
|
|
}
|
|
|
|
// Accumulate emitter and leakage flow
|
|
v = hyd->EmitterFlow[i];
|
|
flowBalance.emitterDemand += v;
|
|
flowBalance.totalOutflow += v;
|
|
v = hyd->LeakageFlow[i];
|
|
flowBalance.leakageDemand += v;
|
|
flowBalance.totalOutflow += v;
|
|
|
|
// Accumulate demand deficit flow
|
|
if (hyd->DemandModel == PDA && hyd->FullDemand[i] > 0.0)
|
|
{
|
|
deficit = hyd->FullDemand[i] - hyd->DemandFlow[i];
|
|
if (deficit > 0.0)
|
|
flowBalance.deficitDemand += deficit;
|
|
}
|
|
}
|
|
|
|
// Examine each tank/reservoir node
|
|
for (j = 1; j <= net->Ntanks; j++)
|
|
{
|
|
i = net->Tank[j].Node;
|
|
v = hyd->NodeDemand[i];
|
|
|
|
// For a reservoir node
|
|
if (net->Tank[j].A == 0.0)
|
|
{
|
|
if (v >= 0.0)
|
|
flowBalance.totalOutflow += v;
|
|
else
|
|
flowBalance.totalInflow += (-v);
|
|
}
|
|
|
|
// For tank
|
|
else
|
|
flowBalance.storageDemand += v;
|
|
}
|
|
|
|
// Find % leakage for current period
|
|
v = flowBalance.totalInflow;
|
|
if (flowBalance.storageDemand < 0.0) v += (-flowBalance.storageDemand);
|
|
if (v > 0.0)
|
|
hyd->LeakageLoss = flowBalance.leakageDemand / v * 100.0;
|
|
|
|
// Update flow balance for entire run
|
|
hyd->FlowBalance.totalInflow += flowBalance.totalInflow * dt;
|
|
hyd->FlowBalance.totalOutflow += flowBalance.totalOutflow * dt;
|
|
hyd->FlowBalance.consumerDemand += flowBalance.consumerDemand * dt;
|
|
hyd->FlowBalance.emitterDemand += flowBalance.emitterDemand * dt;
|
|
hyd->FlowBalance.leakageDemand += flowBalance.leakageDemand * dt;
|
|
hyd->FlowBalance.deficitDemand += flowBalance.deficitDemand * dt;
|
|
hyd->FlowBalance.storageDemand += flowBalance.storageDemand * dt;
|
|
}
|
|
|
|
void endflowbalance(Project *pr)
|
|
/*
|
|
**-------------------------------------------------------------------
|
|
** Input: none
|
|
** Output: none
|
|
** Purpose: finalizes components of the system flow balance.
|
|
**-------------------------------------------------------------------
|
|
*/
|
|
{
|
|
Hydraul *hyd = &pr->hydraul;
|
|
Times *time = &pr->times;
|
|
|
|
double seconds, qin, qout, qstor, r;
|
|
|
|
if (time->Htime > 0)
|
|
seconds = time->Htime;
|
|
else
|
|
seconds = 1.0;
|
|
hyd->FlowBalance.totalInflow /= seconds;
|
|
hyd->FlowBalance.totalOutflow /= seconds;
|
|
hyd->FlowBalance.consumerDemand /= seconds;
|
|
hyd->FlowBalance.emitterDemand /= seconds;
|
|
hyd->FlowBalance.leakageDemand /= seconds;
|
|
hyd->FlowBalance.deficitDemand /= seconds;
|
|
hyd->FlowBalance.storageDemand /= seconds;
|
|
|
|
qin = hyd->FlowBalance.totalInflow;
|
|
qout = hyd->FlowBalance.totalOutflow;
|
|
qstor = hyd->FlowBalance.storageDemand;
|
|
if (qstor > 0.0)
|
|
qout += qstor;
|
|
else
|
|
qin -= qstor;
|
|
if (qin == qout)
|
|
r = 1.0;
|
|
else if (qin > 0.0)
|
|
r = qout / qin;
|
|
else
|
|
r = 0.0;
|
|
hyd->FlowBalance.ratio = r;
|
|
}
|