@@ -1715,18 +1715,19 @@ RC DHWHEATER::wh_InstUEFInit() // one-time setup for UEF-based instantaneous mo
17151715// returns RCOK on success
17161716// else other -- do not run
17171717{
1718- #if 1
1719- // parameters used in deriving runtime coefficients
1718+ // parameters used in deriving runtime coefficients
1719+ // from Tankless WH consumption calculations for ACM.18.doc
1720+ // J. Lutz, 28 July 2017
17201721struct UEFPARAMS
17211722{ float flowMax; float flowRE;
17221723 float A; float B; float qOutUEF; float qOutRE; float durRE; float honUEF;
17231724};
17241725static 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 },
1726+ // size flowMax flowRE A B qOutUEF qOutRE durRE honUEF
1727+ { /* very small*/ 0 .f , 1 .f , 10 .f , 3 . 62150f , 5452 .f , 1090 .f , 2 .000f , 0 .1667f },
1728+ { /* low*/ 1 .7f , 1 .7f , 22 .3529f , 5 . 78215f , 20718 .f , 8178 .f , 8 .824f , 0 .4275f },
1729+ { /* medium*/ 2 .8f , 1 .7f , 32 .3529f , 6 . 30610f , 29987 .f , 8178 .f , 8 .824f , 0 .5941f },
1730+ { /* high*/ 4 .f , 3 .f , 28 .00f , 6 . 42050f , 45798 .f , 14721 .f , 9 .000f , 0 .6542f },
17301731{ /* terminator*/ 9999999 .f }};
17311732
17321733 RC rc = RCOK;
@@ -1740,9 +1741,14 @@ static const UEFPARAMS UEFParams[] = {
17401741 const UEFPARAMS& UP = UEFParams[ iSize];
17411742
17421743 // 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 .);
1744+ double F;
1745+ if (wh_annualFuel < .000001f )
1746+ F = 1 .; // nothing known about electrical use
1747+ else
1748+ { F = 0.99 ;
1749+ if (wh_annualFuel > 0 .f ) // insurance
1750+ F = 1 ./(1 . + (wh_annualElec/wh_annualFuel)*3412 ./100000 .);
1751+ }
17461752
17471753 // electrical power during operation (recovery), W
17481754 double Pe = (wh_annualElec * 1000 ./365 . - wh_stbyElec * (24 .-UP.honUEF ))
@@ -1777,62 +1783,6 @@ static const UEFPARAMS UEFParams[] = {
17771783 // wh_cycLossElec = 0.f; // electricity use per start, Btu
17781784 // unused in revised model 5-24-2017
17791785
1780- #else
1781- // parameters used in deriving runtime coefficients
1782- struct UEFPARAMS
1783- { float flowMax; float flowRE;
1784- float A; float B; float C; float D; float E; float honUEF;
1785- };
1786- static const UEFPARAMS UEFParams[] = {
1787- // size flowMax flowRE A B C D E honUEF
1788- { /*very small*/ 0.f, 1.f, 5452.f, 9814.f, -8.00f, 1090.f, 2.000f, 0.1667f },
1789- { /*low*/ 1.7f, 1.7f, 20718.f, 89960.f, -74.71f, 8178.f, 8.824f, 0.4275f },
1790- { /*medium*/ 2.8f, 1.7f, 29987.f, 98138.f, -73.53f, 8178.f, 8.824f, 0.5941f },
1791- { /*high*/ 4.f, 3.f, 45798.f, 206090.f, -98.00f, 14721.f, 9.000f, 0.6542f },
1792- { /*terminator*/ 9999999.f }};
1793-
1794- RC rc = RCOK;
1795-
1796- // determine size bin
1797- int iSize;
1798- for (iSize=0; iSize < 4; iSize++)
1799- { if (UEFParams[ iSize+1].flowMax > wh_ratedFlow)
1800- break;
1801- }
1802- const UEFPARAMS& UP = UEFParams[ iSize];
1803-
1804- // fraction of energy use that is fuel
1805- double F = 0.99;
1806- if (wh_annualFuel > 0.f) // insurance
1807- F = 1./(1. + (wh_annualElec/wh_annualFuel)*3412./100000.);
1808-
1809- // electrical power during operation (recovery), W
1810- double Pe = (wh_annualElec * 1000./365. - wh_stbyElec * (24.-UP.honUEF))
1811- / UP.honUEF;
1812- if (Pe < 0)
1813- rc |= oer( "Inconsistent input for whAnnualElec (=%.2f kWh) and whStbyElec (=%.2f W).\n"
1814- " Derived operating electrical power is < 0.",
1815- wh_annualElec, wh_stbyElec);
1816-
1817- float P = F * (UP.A/wh_UEF - UP.B/ wh_eff) / UP.C; // fuel at flow=flowRE and deltaT=67, Btu/min
1818-
1819- wh_cycLossFuel = F * (UP.D / wh_eff) - P*UP.E; // startup fuel, Btu/cycle
1820-
1821-
1822- // max flow per tick, gal-F/tick
1823- // Top.tp_subhrTickDur = tick duration, min
1824- wh_maxFlowX = wh_ratedFlow * Top.tp_subhrTickDur * 67.f;
1825-
1826- // fuel input: Btu/tick at flow=maxFlow and deltaT=67
1827- wh_maxInpX = P // Btu/min at flow=flowRE and deltaT=67
1828- * (wh_ratedFlow / UP.flowRE) // scale to max flow
1829- * Top.tp_subhrTickDur; // scale to actual tick duration
1830-
1831- // no electricity use pending model development
1832- wh_operElec = Pe * BtuperWh; // electrical power during opration, Btuh
1833- // wh_cycLossElec = 0.f; // electricity use per start, Btu
1834- // unused in revised model 5-24-2017
1835- #endif
18361786 return rc;
18371787} // DHWHEATER::wh_InstUEFInit
18381788// ----------------------------------------------------------------------------
@@ -1858,7 +1808,6 @@ RC DHWHEATER::wh_InstUEFDoSubhr(
18581808 // max vol that can be heated in 1 tick
18591809 double drawFullLoad = wh_maxFlowX / deltaT;
18601810
1861- #if 1
18621811 // carry-forward: instantaneous heaters throttle flow to maintain temp.
18631812 // here represented by carrying forward a limited amount of unmet load
18641813 wh_HPWHxBU = 0 .; // heat in excess of capacity (after carry-forward)
@@ -1886,8 +1835,18 @@ RC DHWHEATER::wh_InstUEFDoSubhr(
18861835 else
18871836 nTickFullLoad += drawForTick / drawFullLoad;
18881837 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 .);
1838+ { double offMins = wh_stbyTicks * Top.tp_subhrTickDur ;
1839+ #if 1 // exponential cool-down, 7-29-2017
1840+ // exponential cooldown
1841+ static const double TC = 50.06027 ; // cooldown time constant
1842+ double r = offMins / TC;
1843+ nColdStarts += r > 10 . ? 1 . : 1 .-exp (-r); // avoid underflow
1844+ // printf( "\n%0.2f %0.4f", offMins, nColdStarts);
1845+
1846+ #else
1847+ x // cold start after 30 min, linearly reduced for short times
1848+ x nColdStarts += min( 1., offMins / 30.);
1849+ #endif
18911850 wh_stbyTicks = 0 ;
18921851 }
18931852 }
@@ -1903,40 +1862,6 @@ RC DHWHEATER::wh_InstUEFDoSubhr(
19031862 // double startElec = wh_cycLossElec * nTickStart; // unused in revised model
19041863 // standby in ticks w/o draw
19051864 double stbyElec = wh_stbyElec * (Top.tp_nSubhrTicks -nTickNZDraw) * tickDurHr;
1906- #else
1907- double volxBU = 0.; // volume in excess of capacity, gal
1908- int nTickNZDraw = 0; // count of ticks with draw > 0
1909- double nTickFullLoad = 0.; // fractional ticks of equiv full load
1910- int nTickStart = 0; // # of startup ticks (draw changes 0 -> nz)
1911- for (int iT=0; !rc && iT<Top.tp_nSubhrTicks; iT++)
1912- {
1913- double drawForTick = draw[ iT]*scale*wh_mixDownF + drawLoss; // gal
1914- if (drawForTick > 0.)
1915- { nTickNZDraw++;
1916- if (drawForTick > drawFullLoad)
1917- { nTickFullLoad += 1.; // full capacity operation
1918- volxBU += drawForTick - drawFullLoad; // excess demand, gal
1919- }
1920- else
1921- nTickFullLoad += drawForTick / drawFullLoad;
1922- if (wh_stbyTicks) // if no draw in prior tick
1923- nTickStart++; // count start
1924- }
1925- else
1926- // standby
1927- wh_stbyTicks++; // reset draw duration
1928- }
1929-
1930- double tickDurHr = Top.tp_subhrTickDur / 60.; // tick duration, hr
1931- double rcovFuel = wh_maxInpX * nTickFullLoad;
1932- double startFuel = wh_cycLossFuel * nTickStart;
1933- double rcovElec = wh_operElec * nTickNZDraw * tickDurHr; // assume operation for entire tick with any draw
1934- // double startElec = wh_cycLossElec * nTickStart; // unused in revised model
1935- // standby in ticks w/o draw
1936- double stbyElec = wh_stbyElec * (Top.tp_nSubhrTicks-nTickNZDraw) * tickDurHr;
1937- wh_HPWHxBU = 8.345 * volxBU * deltaT;
1938- // excess heating required to meet ws_tUse
1939- #endif
19401865
19411866 // energy use accounting, Btu
19421867 double inFuel = rcovFuel + startFuel;
0 commit comments