Skip to content

Commit 4041a0a

Browse files
committed
CSE 0.834
Instantaneous WH 2nd rev
1 parent d2fe451 commit 4041a0a

File tree

5 files changed

+126
-6
lines changed

5 files changed

+126
-6
lines changed

src/CNCULT.CPP

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,6 +1776,7 @@ CULT( "whEF", DAT, DHWHEATER_EF, 0, 0, VEOI, TYFL, 0, 0.82f
17761776
CULT( "whUEF", DAT, DHWHEATER_UEF, 0, 0, VEOI, TYFL, 0, 0.f, N, N),
17771777
CULT( "whStbyElec", DAT, DHWHEATER_STBYELEC, 0, 0, VEOI, TYFL, 0, 4.f, N, N),
17781778
CULT( "whRatedFlow", DAT, DHWHEATER_RATEDFLOW, 0, 0, VEOI, TYFL, 0, 0.f, N, N),
1779+
CULT( "whLoadCFwdF", DAT, DHWHEATER_LOADCFWDF, 0, 0, VEOI, TYFL, 0, 1.f, N, N),
17791780
CULT( "whAnnualFuel",DAT, DHWHEATER_ANNUALFUEL,0, 0, VEOI, TYFL, 0, 0.f, N, N),
17801781
CULT( "whAnnualElec",DAT, DHWHEATER_ANNUALELEC,0, 0, VEOI, TYFL, 0, 0.f, N, N),
17811782
CULT( "whResHtPwr", DAT, DHWHEATER_RESHTPWR,0, 0, VEOI, TYFL, 0, 4500.f, N, N),

src/CNDTYPES.DEF

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ DUCTSEGP -- "class DUCTSEG*" 4 none
498498
HTG "Htg" // space heating incl heat pump compressor
499499
HPHTG "HPHtg" // heat pump backup heat
500500
DHW "DHW" // domestic (service) hot water heating
501-
DHWBU "DHWBU" // domestic (service) not water heating backup (HPWH resistance)
501+
DHWBU "DHWBU" // domestic (service) hot water heating backup (HPWH resistance)
502502
FANC "FanC" // fan energy for AC and cooling ventilation
503503
FANH "FanH" // fan energy for heating
504504
FANV "FanV" // fan energy for IAQ venting

src/CNRECS.DEF

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3409,8 +3409,8 @@ RECORD DHWHEATER "DHWHeater" *RAT // input / runtime DHW heater
34093409
*i FLOAT_GZ wh_UEF; // rated uniform energy factor
34103410
// documentation only re C_WHTYPECH_INSTUEF
34113411
*i FLOAT_GZ wh_ratedFlow; // max rated flow per UEF test, gpm
3412-
*i FLOAT_GZ wh_annualFuel; // annual fuel use per UEF method, therms/yr
3413-
*i FLOAT_GZ wh_annualElec; // annual electricity use per UEF method, kWh/yr
3412+
*i FLOAT_GEZ wh_annualFuel; // annual fuel use per UEF method, therms/yr
3413+
*i FLOAT_GEZ wh_annualElec; // annual electricity use per UEF method, kWh/yr
34143414
*declare "RC wh_InstUEFInit();"
34153415
*declare "RC wh_InstUEFDoSubhr( double* draw, double scale, double xLoss);"
34163416

@@ -3435,6 +3435,9 @@ RECORD DHWHEATER "DHWHeater" *RAT // input / runtime DHW heater
34353435
// draws are reduced to balance load at ws_tUse.
34363436
*s INT wh_stbyTicks; // time since last draw, for HPWH and INSTUEF, ticks
34373437
// re startup (cyclic) loss model
3438+
*s DBL wh_loadCFwd;
3439+
*i DBL wh_loadCFwdMax;
3440+
*i FLOAT_GEZ wh_loadCFwdF;
34383441

34393442
*i TI wh_elecMtri // meter for system electricity use (default = parent ws_elecMtri)
34403443
*i TI wh_fuelMtri // meter for system fuel use (default = parent ws_electMtri)

src/DHWCalc.cpp

Lines changed: 116 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,9 @@ RC DHWHEATER::wh_CkF() // water heater input check / default
970970
rc |= requireN( whenTy, DHWHEATER_UEF, DHWHEATER_RATEDFLOW, DHWHEATER_ANNUALFUEL,
971971
DHWHEATER_ANNUALELEC, DHWHEATER_EFF, 0);
972972
ignoreN( whenTy, DHWHEATER_EF, 0);
973+
if (wh_UEF > wh_eff)
974+
rc |= oer( "whEff (%0.3f) must be >= whUEF (%0.3f)",
975+
wh_eff, wh_UEF);
973976
// note wh_vol check below (wh_vol=0 OK, else error)
974977
}
975978
else if (wh_heatSrc == C_WHHEATSRCCH_ASHP
@@ -1712,6 +1715,69 @@ RC DHWHEATER::wh_InstUEFInit() // one-time setup for UEF-based instantaneous mo
17121715
// returns RCOK on success
17131716
// else other -- do not run
17141717
{
1718+
#if 1
1719+
// parameters used in deriving runtime coefficients
1720+
struct UEFPARAMS
1721+
{ float flowMax; float flowRE;
1722+
float A; float B; float qOutUEF; float qOutRE; float durRE; float honUEF;
1723+
};
1724+
static const UEFPARAMS UEFParams[] = {
1725+
// size flowMax flowRE A B qOutUEF qOutRE durRE honUEF
1726+
{ /*very small*/ 0.f, 1.f, 10.f, 5.3500f, 5452.f, 1090.f, 2.000f, 0.1667f },
1727+
{ /*low*/ 1.7f, 1.7f, 22.3529f, 9.0882f, 20718.f, 8178.f, 8.824f, 0.4275f },
1728+
{ /*medium*/ 2.8f, 1.7f, 32.3529f, 9.6020f, 29987.f, 8178.f, 8.824f, 0.5941f },
1729+
{ /*high*/ 4.f, 3.f, 28.00f, 9.7902f, 45798.f, 14721.f, 9.000f, 0.6542f },
1730+
{ /*terminator*/ 9999999.f }};
1731+
1732+
RC rc = RCOK;
1733+
1734+
// determine size bin
1735+
int iSize;
1736+
for (iSize=0; iSize < 4; iSize++)
1737+
{ if (UEFParams[ iSize+1].flowMax > wh_ratedFlow)
1738+
break;
1739+
}
1740+
const UEFPARAMS& UP = UEFParams[ iSize];
1741+
1742+
// fraction of energy use that is fuel
1743+
double F = 0.99;
1744+
if (wh_annualFuel > 0.f) // insurance
1745+
F = 1./(1. + (wh_annualElec/wh_annualFuel)*3412./100000.);
1746+
1747+
// electrical power during operation (recovery), W
1748+
double Pe = (wh_annualElec * 1000./365. - wh_stbyElec * (24.-UP.honUEF))
1749+
/ UP.honUEF;
1750+
if (Pe < 0)
1751+
rc |= oer( "Inconsistent input for whAnnualElec (=%.2f kWh) and whStbyElec (=%.2f W).\n"
1752+
" Derived operating electrical power is < 0.",
1753+
wh_annualElec, wh_stbyElec);
1754+
1755+
float P = (UP.qOutUEF/wh_UEF - UP.B*UP.qOutRE/wh_eff) / (UP.A - UP.B*UP.durRE);
1756+
float Lcyc = UP.qOutRE/wh_eff - P*UP.durRE;
1757+
1758+
float Pf = F * P; // fuel at flow=flowRE and deltaT=67, Btu/min
1759+
wh_cycLossFuel = F * Lcyc; // startup fuel, Btu/cycle
1760+
1761+
// max flow per tick, gal-F/tick
1762+
// Top.tp_subhrTickDur = tick duration, min
1763+
wh_maxFlowX = wh_ratedFlow * Top.tp_subhrTickDur * 67.f;
1764+
1765+
// maximum load carry forward, Btu
1766+
// user input wh_loadCFwdF = multiplier for rated capacity
1767+
// (approximately allowed catch-up time, hr)
1768+
wh_loadCFwdMax = wh_loadCFwdF * wh_ratedFlow * 8.345 * 67. * 60.;
1769+
1770+
// fuel input: Btu/tick at flow=maxFlow and deltaT=67
1771+
wh_maxInpX = Pf // Btu/min at flow=flowRE and deltaT=67
1772+
* (wh_ratedFlow / UP.flowRE) // scale to max flow
1773+
* Top.tp_subhrTickDur; // scale to actual tick duration
1774+
1775+
// no electricity use pending model development
1776+
wh_operElec = Pe * BtuperWh; // electrical power during opration, Btuh
1777+
// wh_cycLossElec = 0.f; // electricity use per start, Btu
1778+
// unused in revised model 5-24-2017
1779+
1780+
#else
17151781
// parameters used in deriving runtime coefficients
17161782
struct UEFPARAMS
17171783
{ float flowMax; float flowRE;
@@ -1766,6 +1832,7 @@ static const UEFPARAMS UEFParams[] = {
17661832
wh_operElec = Pe * BtuperWh; // electrical power during opration, Btuh
17671833
// wh_cycLossElec = 0.f; // electricity use per start, Btu
17681834
// unused in revised model 5-24-2017
1835+
#endif
17691836
return rc;
17701837
} // DHWHEATER::wh_InstUEFInit
17711838
//----------------------------------------------------------------------------
@@ -1785,11 +1852,58 @@ RC DHWHEATER::wh_InstUEFDoSubhr(
17851852

17861853
float deltaT = max( 1., pWS->ws_tUse - pWS->ws_tInlet); // temp rise, F
17871854
// max( 1, dT) to prevent x/0
1788-
double drawLoss = xLoss / (8.345*deltaT);
1855+
double qPerGal = 8.345 * deltaT;
1856+
double drawLoss = xLoss / qPerGal;
17891857

17901858
// max vol that can be heated in 1 tick
17911859
double drawFullLoad = wh_maxFlowX / deltaT;
17921860

1861+
#if 1
1862+
// carry-forward: instantaneous heaters throttle flow to maintain temp.
1863+
// here represented by carrying forward a limited amount of unmet load
1864+
wh_HPWHxBU = 0.; // heat in excess of capacity (after carry-forward)
1865+
// provided by virtual resistance heat
1866+
// prevents gaming compliance via undersizing
1867+
int nTickNZDraw = 0; // count of ticks with draw > 0
1868+
double nTickFullLoad = 0.; // fractional ticks of equiv full load
1869+
double nColdStarts = 0.; // # of cold startups
1870+
for (int iT=0; !rc && iT<Top.tp_nSubhrTicks; iT++)
1871+
{ double drawForTick =
1872+
draw[ iT]*scale*wh_mixDownF
1873+
+ drawLoss
1874+
+ wh_loadCFwd / qPerGal; // attempt to meet entire carry-forward load
1875+
wh_loadCFwd= 0.; // clear carry-forward, if not met, reset just below
1876+
if (drawForTick > 0.)
1877+
{ nTickNZDraw++;
1878+
if (drawForTick > drawFullLoad)
1879+
{ nTickFullLoad += 1.; // full capacity operation
1880+
wh_loadCFwd = qPerGal * (drawForTick - drawFullLoad); // unmet load
1881+
if (wh_loadCFwd > wh_loadCFwdMax)
1882+
{ wh_HPWHxBU += wh_loadCFwd - wh_loadCFwdMax; // excess heating required to meet ws_tUse
1883+
wh_loadCFwd = wh_loadCFwdMax;
1884+
}
1885+
}
1886+
else
1887+
nTickFullLoad += drawForTick / drawFullLoad;
1888+
if (wh_stbyTicks) // if no draw in prior tick
1889+
{ // cold start after 30 min, linearly reduced for short times
1890+
nColdStarts += min( 1., wh_stbyTicks * Top.tp_subhrTickDur / 30.);
1891+
wh_stbyTicks = 0;
1892+
}
1893+
}
1894+
else
1895+
// standby
1896+
wh_stbyTicks++; // count conseq ticks w/o draw
1897+
}
1898+
1899+
double tickDurHr = Top.tp_subhrTickDur / 60.; // tick duration, hr
1900+
double rcovFuel = wh_maxInpX * nTickFullLoad;
1901+
double startFuel = wh_cycLossFuel * nColdStarts;
1902+
double rcovElec = wh_operElec * nTickNZDraw * tickDurHr; // assume operation for entire tick with any draw
1903+
// double startElec = wh_cycLossElec * nTickStart; // unused in revised model
1904+
// standby in ticks w/o draw
1905+
double stbyElec = wh_stbyElec * (Top.tp_nSubhrTicks-nTickNZDraw) * tickDurHr;
1906+
#else
17931907
double volxBU = 0.; // volume in excess of capacity, gal
17941908
int nTickNZDraw = 0; // count of ticks with draw > 0
17951909
double nTickFullLoad = 0.; // fractional ticks of equiv full load
@@ -1820,9 +1934,9 @@ RC DHWHEATER::wh_InstUEFDoSubhr(
18201934
// double startElec = wh_cycLossElec * nTickStart; // unused in revised model
18211935
// standby in ticks w/o draw
18221936
double stbyElec = wh_stbyElec * (Top.tp_nSubhrTicks-nTickNZDraw) * tickDurHr;
1823-
18241937
wh_HPWHxBU = 8.345 * volxBU * deltaT;
18251938
// excess heating required to meet ws_tUse
1939+
#endif
18261940

18271941
// energy use accounting, Btu
18281942
double inFuel = rcovFuel + startFuel;

src/csevrsn.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@
1414
// version # for current build
1515
// change ONLY here
1616
#define CSEVRSN_MAJOR 0
17-
#define CSEVRSN_MINOR 833
17+
#define CSEVRSN_MINOR 834
1818

1919
// version # as quoted text ("x.xxx")
2020
#define CSEVRSN_TEXT MAKE_LIT(CSEVRSN_MAJOR##.##CSEVRSN_MINOR)
2121

2222
// ONLY comments below here
2323

2424
/* History:
25+
0.834: UEF model 2nd rev (cooldown-time-dependent startup energy, load carry-forward)
26+
committed 7-17-2017
2527
0.833: revised UEF model (includes electricity use), committed 5-25-2017
2628
0.832: preliminary UEF instantaneous DHW model, committed 5-19-2017
2729
0.831: missing TDV file -> UNSET data,

0 commit comments

Comments
 (0)