Adding Pipe Leakage Modeling

This commit is contained in:
Lew Rossman
2024-06-26 11:34:19 -04:00
parent cc9105fda6
commit 037ca41af6
25 changed files with 1365 additions and 221 deletions

View File

@@ -8,7 +8,7 @@
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 02/14/2022
Last Updated: 06/15/2024
******************************************************************************
*/
@@ -47,6 +47,7 @@ static double newflows(Project *, Hydbalance *);
static void newlinkflows(Project *, Hydbalance *, double *, double *);
static void newemitterflows(Project *, Hydbalance *, double *, double *);
static void newdemandflows(Project *, Hydbalance *, double *, double *);
static void newleakageflows(Project *, Hydbalance *, double *, double *);
static void checkhydbalance(Project *, Hydbalance *);
static int hasconverged(Project *, double *, Hydbalance *);
@@ -93,7 +94,6 @@ int hydsolve(Project *pr, int *iter, double *relerr)
int valveChange; // Valve status change flag
int statChange; // Non-valve status change flag
Hydbalance hydbal; // Hydraulic balance errors
double fullDemand; // Full demand for a node (cfs)
// Initialize status checking & relaxation factor
nextcheck = hyd->CheckFreq;
@@ -195,12 +195,12 @@ int hydsolve(Project *pr, int *iter, double *relerr)
errcode = 110;
}
// Store actual junction outflow in NodeDemand & full demand in DemandFlow
// Save total outflow (NodeDemand) at each junction
for (i = 1; i <= net->Njuncs; i++)
{
fullDemand = hyd->NodeDemand[i];
hyd->NodeDemand[i] = hyd->DemandFlow[i] + hyd->EmitterFlow[i];
hyd->DemandFlow[i] = fullDemand;
hyd->NodeDemand[i] = hyd->DemandFlow[i] +
hyd->EmitterFlow[i] +
hyd->LeakageFlow[i];
}
// Save convergence info
@@ -381,6 +381,7 @@ double newflows(Project *pr, Hydbalance *hbal)
newlinkflows(pr, hbal, &qsum, &dqsum);
newemitterflows(pr, hbal, &qsum, &dqsum);
newdemandflows(pr, hbal, &qsum, &dqsum);
if (hyd->HasLeakage) newleakageflows(pr, hbal, &qsum, &dqsum);
// Return ratio of total flow corrections to total flow
if (qsum > hyd->Hacc) return (dqsum / qsum);
@@ -514,6 +515,45 @@ void newemitterflows(Project *pr, Hydbalance *hbal, double *qsum,
}
void newleakageflows(Project *pr, Hydbalance *hbal, double *qsum,
double *dqsum)
/*
**----------------------------------------------------------------
** Input: hbal = ptr. to hydraulic balance information
** qsum = sum of current system flows
** dqsum = sum of system flow changes
** Output: updates hbal, qsum and dqsum
** Purpose: updates nodal leakage flows after new nodal heads computed
**----------------------------------------------------------------
*/
{
Network *net = &pr->network;
Hydraul *hyd = &pr->hydraul;
int i;
double dq;
for (i = 1; i <= net->Njuncs; i++)
{
// Update leakage flow at node i
dq = leakageflowchange(pr, i);
if (dq == 0.0) continue;
// Update system flow summation
*qsum += ABS(hyd->LeakageFlow[i]);
*dqsum += ABS(dq);
// Update identity of element with max. flow change
if (ABS(dq) > hbal->maxflowchange)
{
hbal->maxflowchange = ABS(dq);
hbal->maxflownode = i;
hbal->maxflowlink = -1;
}
}
}
void newdemandflows(Project *pr, Hydbalance *hbal, double *qsum, double *dqsum)
/*
**----------------------------------------------------------------
@@ -546,7 +586,7 @@ void newdemandflows(Project *pr, Hydbalance *hbal, double *qsum, double *dqsum)
for (i = 1; i <= net->Njuncs; i++)
{
// Skip junctions with no positive demand
if (hyd->NodeDemand[i] <= 0.0) continue;
if (hyd->FullDemand[i] <= 0.0) continue;
// Find change in demand flow (see hydcoeffs.c)
demandheadloss(pr, i, dp, n, &hloss, &hgrad);
@@ -555,8 +595,8 @@ void newdemandflows(Project *pr, Hydbalance *hbal, double *qsum, double *dqsum)
dq *= hyd->RelaxFactor;
// Prevent a flow change greater than full demand
if (fabs(dq) > 0.4 * hyd->NodeDemand[i])
dq = 0.4 * SGN(dq) * hyd->NodeDemand[i];
if (fabs(dq) > 0.4 * hyd->FullDemand[i])
dq = 0.4 * SGN(dq) * hyd->FullDemand[i];
hyd->DemandFlow[i] -= dq;
// Update system flow summation
@@ -641,11 +681,15 @@ int hasconverged(Project *pr, double *relerr, Hydbalance *hbal)
if (hyd->FlowChangeLimit > 0.0 &&
hbal->maxflowchange > hyd->FlowChangeLimit) return 0;
// Check for node leakage convergence
if (hyd->HasLeakage && !leakagehasconverged(pr)) return 0;
// Check for pressure driven analysis convergence
if (hyd->DemandModel == PDA) return pdaconverged(pr);
return 1;
}
int pdaconverged(Project *pr)
/*
**--------------------------------------------------------------
@@ -659,47 +703,32 @@ int pdaconverged(Project *pr)
Hydraul *hyd = &pr->hydraul;
const double QTOL = 0.0001; // 0.0001 cfs ~= 0.005 gpm ~= 0.2 lpm)
int i, converged = 1;
double totalDemand = 0.0, totalReduction = 0.0;
int i;
double dp = hyd->Preq - hyd->Pmin;
double p, q, r;
hyd->DeficientNodes = 0;
hyd->DemandReduction = 0.0;
// Add up number of junctions with demand deficits
// Examine each network junction
for (i = 1; i <= pr->network.Njuncs; i++)
{
// Skip nodes whose required demand is non-positive
if (hyd->NodeDemand[i] <= 0.0) continue;
if (hyd->FullDemand[i] <= 0.0) continue;
// Evaluate demand equation at current pressure solution
p = hyd->NodeHead[i] - pr->network.Node[i].El;
if (p <= hyd->Pmin)
q = 0.0;
else if (p >= hyd->Preq)
q = hyd->NodeDemand[i];
q = hyd->FullDemand[i];
else
{
r = (p - hyd->Pmin) / dp;
q = hyd->NodeDemand[i] * pow(r, hyd->Pexp);
q = hyd->FullDemand[i] * pow(r, hyd->Pexp);
}
// Check if demand has not converged
if (fabs(q - hyd->DemandFlow[i]) > QTOL)
converged = 0;
// Accumulate total required demand and demand deficit
if (hyd->DemandFlow[i] + QTOL < hyd->NodeDemand[i])
{
hyd->DeficientNodes++;
totalDemand += hyd->NodeDemand[i];
totalReduction += hyd->NodeDemand[i] - hyd->DemandFlow[i];
}
}
if (totalDemand > 0.0)
hyd->DemandReduction = totalReduction / totalDemand * 100.0;
return converged;
if (fabs(q - hyd->DemandFlow[i]) > QTOL) return 0;
}
return 1;
}