More robust method for handling zero/low flows (#164)

This commit is contained in:
Lew Rossman
2018-09-12 10:38:01 -04:00
parent dab7be8446
commit e45a23c4ef
2 changed files with 28 additions and 15 deletions

View File

@@ -28,9 +28,6 @@ const double AA = -1.5634601348517065795e+00; // -2*.9*2/ln(10)
const double AB = 3.28895476345399058690e-03; // 5.74/(4000^.9) const double AB = 3.28895476345399058690e-03; // 5.74/(4000^.9)
const double AC = -5.14214965799093883760e-03; // AA*AB const double AC = -5.14214965799093883760e-03; // AA*AB
// Cutoff flow for using linear head loss relation
const double Q_CUTOFF = 1.0e-5;
// External functions // External functions
//void resistcoeff(EN_Project *pr, int k); //void resistcoeff(EN_Project *pr, int k);
//void headlosscoeffs(EN_Project *pr); //void headlosscoeffs(EN_Project *pr);
@@ -74,10 +71,12 @@ void resistcoeff(EN_Project *pr, int k)
*/ */
{ {
double e, d, L; double e, d, L;
EN_Network *net = &pr->network; EN_Network *net = &pr->network;
hydraulics_t *hyd = &pr->hydraulics; hydraulics_t *hyd = &pr->hydraulics;
Slink *link = &net->Link[k]; Slink *link = &net->Link[k];
link->Qa = 0.0;
switch (link->Type) { switch (link->Type) {
// ... Link is a pipe. Compute resistance based on headloss formula. // ... Link is a pipe. Compute resistance based on headloss formula.
@@ -91,14 +90,20 @@ void resistcoeff(EN_Project *pr, int k)
switch (hyd->Formflag) switch (hyd->Formflag)
{ {
case HW: case HW:
// ... resistance coeff.
link->R = 4.727 * L / pow(e, hyd->Hexp) / pow(d, 4.871); link->R = 4.727 * L / pow(e, hyd->Hexp) / pow(d, 4.871);
// ... flow below which linear head loss applies
link->Qa = pow(hyd->RQtol / hyd->Hexp / link->R, 1.17371);
break; break;
case DW: case DW:
link->R = L / 2.0 / 32.2 / d / SQR(PI * SQR(d) / 4.0); link->R = L / 2.0 / 32.2 / d / SQR(PI * SQR(d) / 4.0);
break; break;
case CM: case CM:
// ... resistance coeff.
link->R = SQR(4.0 * e / (1.49 * PI * SQR(d))) * link->R = SQR(4.0 * e / (1.49 * PI * SQR(d))) *
pow((d / 4.0), -1.333) * L; pow((d / 4.0), -1.333) * L;
// ... flow below which linear head loss applies
link->Qa = hyd->RQtol / 2.0 / link->R;
} }
break; break;
@@ -384,16 +389,20 @@ void emitheadloss(EN_Project *pr, int i, double *hloss, double *hgrad)
{ {
double ke; double ke;
double q; double q;
double qa;
hydraulics_t *hyd = &pr->hydraulics; hydraulics_t *hyd = &pr->hydraulics;
// Set adjusted emitter coeff. // Set adjusted emitter coeff.
ke = MAX(CSMALL, pr->network.Node[i].Ke); ke = MAX(CSMALL, pr->network.Node[i].Ke);
// Find flow below which head loss is linear
qa = pow(hyd->RQtol / ke / hyd->Qexp, 1.0 / (hyd->Qexp - 1.0));
// Use linear head loss relation for small flow // Use linear head loss relation for small flow
q = hyd->EmitterFlows[i]; q = hyd->EmitterFlows[i];
if (fabs(q) <= Q_CUTOFF) if (fabs(q) <= qa)
{ {
*hgrad = ke * pow(Q_CUTOFF, hyd->Qexp) / Q_CUTOFF; *hgrad = hyd->RQtol;
*hloss = (*hgrad) * q; *hloss = (*hgrad) * q;
} }
@@ -595,9 +604,9 @@ void pipecoeff(EN_Project *pr, int k)
// Friction head loss // Friction head loss
// ... use linear relation for small flows // ... use linear relation for small flows
if (q <= Q_CUTOFF) if (q <= pr->network.Link[k].Qa)
{ {
hgrad = r * pow(Q_CUTOFF, hyd->Hexp) / Q_CUTOFF; hgrad = hyd->RQtol;
hloss = hgrad * q; hloss = hgrad * q;
} }
// ... use original formula for other flows // ... use original formula for other flows
@@ -735,6 +744,7 @@ void pumpcoeff(EN_Project *pr, int k)
r, // Flow resistance coeff. r, // Flow resistance coeff.
n, // Flow exponent coeff. n, // Flow exponent coeff.
setting, // Pump speed setting setting, // Pump speed setting
qa, // Flow limit for linear head loss
hloss, // Head loss across pump hloss, // Head loss across pump
hgrad; // Head loss gradient hgrad; // Head loss gradient
@@ -783,9 +793,10 @@ void pumpcoeff(EN_Project *pr, int k)
// Compute head loss and its gradient // Compute head loss and its gradient
// ... use linear approx. to pump curve for small flows // ... use linear approx. to pump curve for small flows
if (q <= Q_CUTOFF) qa = pow(hyd->RQtol / n / r, 1.0 / (n - 1.0));
if (q <= qa)
{ {
hgrad = r * pow(Q_CUTOFF, n) / Q_CUTOFF; hgrad = hyd->RQtol;
hloss = h0 + hgrad * hyd->LinkFlows[k]; hloss = h0 + hgrad * hyd->LinkFlows[k];
} }
// ... use original pump curve for normal flows // ... use original pump curve for normal flows
@@ -1117,7 +1128,7 @@ void valvecoeff(EN_Project *pr, int k)
**-------------------------------------------------------------- **--------------------------------------------------------------
*/ */
{ {
double flow, q, y, hgrad; double flow, q, y, qa, hgrad;
EN_Network *net = &pr->network; EN_Network *net = &pr->network;
hydraulics_t *hyd = &pr->hydraulics; hydraulics_t *hyd = &pr->hydraulics;
@@ -1139,9 +1150,10 @@ void valvecoeff(EN_Project *pr, int k)
{ {
// Adjust for very small flow // Adjust for very small flow
q = fabs(flow); q = fabs(flow);
if (q <= Q_CUTOFF) qa = hyd->RQtol / 2.0 / link->Km;
if (q <= qa)
{ {
hgrad = link->Km * Q_CUTOFF; hgrad = hyd->RQtol;
y = flow; y = flow;
} }
else else

View File

@@ -410,7 +410,8 @@ typedef struct /* LINK OBJECT */
double Kb; /* Bulk react. coeff */ double Kb; /* Bulk react. coeff */
double Kw; /* Wall react. coeff */ double Kw; /* Wall react. coeff */
double R; /* Flow resistance */ double R; /* Flow resistance */
double Rc; /* Reaction cal */ double Rc; /* Reaction coeff. */
double Qa; // Low flow limit
EN_LinkType Type; /* Link type */ EN_LinkType Type; /* Link type */
StatType Stat; /* Initial status */ StatType Stat; /* Initial status */
char Rpt; /* Reporting flag */ char Rpt; /* Reporting flag */