@@ -961,11 +961,22 @@ RC DHWHEATER::wh_CkF() // water heater input check / default
961961 ignoreN ( whenHs, DHWHEATER_RESHTPWR, DHWHEATER_RESHTPWR2, 0 );
962962
963963 if (wh_type != C_WHTYPECH_STRGSML)
964- {
965- if (wh_heatSrc == C_WHHEATSRCCH_ASHP
966- || wh_heatSrc == C_WHHEATSRCCH_ASHPX)
964+ { if (wh_type == C_WHTYPECH_INSTUEF)
965+ { if (IsSet ( DHWHEATER_HEATSRC) && wh_heatSrc != C_WHHEATSRCCH_FUEL)
966+ rc |= ooer ( DHWHEATER_HEATSRC,
967+ " whHeatSrc=%s is not allowed %s (use whHeatSrc=Fuel or omit)" ,
968+ whHsTx, whenTy);
969+ wh_heatSrc = C_WHHEATSRCCH_FUEL;
970+ rc |= requireN ( whenTy, DHWHEATER_UEF, DHWHEATER_RATEDFLOW, DHWHEATER_ANNUALFUEL,
971+ DHWHEATER_ANNUALELEC, DHWHEATER_EFF, 0 );
972+ ignoreN ( whenTy, DHWHEATER_EF, 0 );
973+ // note wh_vol check below (wh_vol=0 OK, else error)
974+ }
975+ else if (wh_heatSrc == C_WHHEATSRCCH_ASHP
976+ || wh_heatSrc == C_WHHEATSRCCH_ASHPX)
967977 rc |= ooer ( DHWHEATER_HEATSRC,
968978 " whHeatSrc=%s is not allowed %s" , whHsTx, whenTy);
979+
969980 if (wh_type == C_WHTYPECH_STRGLRG || wh_type == C_WHTYPECH_INSTLRG)
970981 rc |= require ( DHWHEATER_EFF, whenTy);
971982 else if (wh_type == C_WHTYPECH_INSTSML)
@@ -1697,22 +1708,23 @@ RC DHWHEATER::wh_HPWHDoSubhr( // HPWH subhour
16971708} // DHWHEATER::wh_HPWHDoSubhr
16981709// -----------------------------------------------------------------------------
16991710RC DHWHEATER::wh_InstUEFInit () // one-time setup for UEF-based instantaneous model
1711+ // returns RCOK on success
1712+ // else other -- do not run
17001713{
1701- #if 1
17021714// parameters used in deriving runtime coefficients
17031715struct UEFPARAMS
17041716{ float flowMax; float flowRE;
1705- float A; float B; float C; float D; float E;
1717+ float A; float B; float C; float D; float E; float honUEF;
17061718};
17071719static const UEFPARAMS UEFParams[] = {
1708- // size flowMax flowRE A B C D E
1709- { /* very small*/ 0 .f , 1 .f , 5452 .f , 9814 .f , -8 .00f , 1090 .f , 2 .000f },
1710- { /* low*/ 1 .7f , 1 .7f , 20718 .f , 89960 .f , -74 .71f , 8178 .f , 8 .824f },
1711- { /* medium*/ 2 .8f , 1 .7f , 29987 .f , 98138 .f , -73 .53f , 8178 .f , 8 .824f },
1712- { /* high*/ 4 .f , 3 .f , 45798 .f , 206090 .f , -98 .00f , 14721 .f , 9 .000f },
1720+ // size flowMax flowRE A B C D E honUEF
1721+ { /* very small*/ 0 .f , 1 .f , 5452 .f , 9814 .f , -8 .00f , 1090 .f , 2 .000f , 0 . 1667f },
1722+ { /* low*/ 1 .7f , 1 .7f , 20718 .f , 89960 .f , -74 .71f , 8178 .f , 8 .824f , 0 . 4275f },
1723+ { /* medium*/ 2 .8f , 1 .7f , 29987 .f , 98138 .f , -73 .53f , 8178 .f , 8 .824f , 0 . 5941f },
1724+ { /* high*/ 4 .f , 3 .f , 45798 .f , 206090 .f , -98 .00f , 14721 .f , 9 .000f , 0 . 6542f },
17131725{ /* terminator*/ 9999999 .f }};
17141726
1715- RC rc = RCOK;
1727+ RC rc = RCOK;
17161728
17171729 // determine size bin
17181730 int iSize;
@@ -1722,9 +1734,23 @@ RC rc = RCOK;
17221734 }
17231735 const UEFPARAMS& UP = UEFParams[ iSize];
17241736
1725- float P = (UP.A /wh_UEF - UP.B / wh_eff) / UP.C ; // Btu/min at flow=flowRE and deltaT=67
1737+ // fraction of energy use that is fuel
1738+ double F = 0.99 ;
1739+ if (wh_annualFuel > 0 .f ) // insurance
1740+ F = 1 ./(1 . + (wh_annualElec/wh_annualFuel)*3412 ./100000 .);
1741+
1742+ // electrical power during operation (recovery), W
1743+ double Pe = (wh_annualElec * 1000 ./365 . - wh_stbyElec * (24 .-UP.honUEF ))
1744+ / UP.honUEF ;
1745+ if (Pe < 0 )
1746+ rc |= oer ( " Inconsistent input for whAnnualElec (=%.2f kWh) and whStbyElec (=%.2f W).\n "
1747+ " Derived operating electrical power is < 0." ,
1748+ wh_annualElec, wh_stbyElec);
1749+
1750+ float P = F * (UP.A /wh_UEF - UP.B / wh_eff) / UP.C ; // fuel at flow=flowRE and deltaT=67, Btu/min
1751+
1752+ wh_cycLossFuel = F * (UP.D / wh_eff) - P*UP.E ; // startup fuel, Btu/cycle
17261753
1727- wh_cycLossFuel = (UP.D / wh_eff) - P*UP.E ; // startup energy, Btu/cycle
17281754
17291755 // max flow per tick, gal-F/tick
17301756 // Top.tp_subhrTickDur = tick duration, min
@@ -1736,56 +1762,9 @@ RC rc = RCOK;
17361762 * Top.tp_subhrTickDur ; // scale to actual tick duration
17371763
17381764 // no electricity use pending model development
1739- wh_operElec = 0 .f ;
1740- wh_stbyElec = 0 .f ;
1741- wh_cycLossElec = 0 .f ;
1742-
1743- #else
1744- // parameters used in UEF tests
1745- struct UEFPARAMS
1746- { float fMax; float qOut; float v; float hOn; float N;
1747- float f1; float qOut1; float v1; float hOn1;
1748- };
1749- static const UEFPARAMS UEFParams[] = {
1750- // size fMax qOut v hon N f1 qout1 v1 hon1
1751- { /*very small*/ 0.f, 5452.f, 10.f, 0.1667f, 9.f, 1.f, 1090.f, 2.f, 0.0333f },
1752- { /*low*/ 1.7f, 20718.f, 38.f, 0.4275f, 11.f, 1.7f, 8178.f, 15.f, 0.1471f },
1753- { /*medium*/ 2.8f, 29987.f, 55.f, 0.5941f, 12.f, 1.7f, 8178.f, 15.f, 0.1471f },
1754- { /*high*/ 4.f, 45798.f, 84.f, 0.6542f, 14.f, 3.f, 14721.f, 27.f, 0.15f },
1755- { /*terminator*/ 9999999.f }};
1756-
1757- RC rc = RCOK;
1758-
1759- // determine size bin
1760- int iSize;
1761- for (iSize=0; iSize < 4; iSize++)
1762- { if (UEFParams[ iSize+1].fMax > wh_ratedFlow)
1763- break;
1764- }
1765- const UEFPARAMS& UP = UEFParams[ iSize];
1766-
1767- float qiElec = wh_annualElec * 3412.f / 365.f;
1768- float qiFuel = wh_annualFuel * 100000.f / 365.f;
1769-
1770-
1771- float TDuef = (UP.v / (60.f *UP.hOn)) / wh_ratedFlow;
1772- wh_cycLossFuel = (qiFuel - wh_ratedInput * TDuef * UP.hOn) / UP.N;
1773-
1774- float Qr = UP.qOut1 / wh_eff;
1775- float TDre = UP.f1 / wh_ratedFlow;
1776- float hStby = 24.f - UP.hOn;
1777- float J = TDre*UP.hOn1 + wh_cycLossFuel / wh_ratedInput;
1778- float K = TDuef*UP.hOn + UP.N * wh_cycLossFuel / wh_ratedInput;
1779-
1780- float qiFuelRe = wh_ratedInput * TDre * UP.hOn1 + wh_cycLossFuel;
1781-
1782- wh_operElec = (qiElec + qiFuelRe - Qr) / (J * hStby + K);
1783-
1784- wh_stbyElec = Qr - qiFuelRe - wh_operElec*J;
1785-
1786- wh_cycLossElec = wh_operElec * wh_cycLossFuel / wh_ratedInput;
1787- #endif
1788-
1765+ wh_operElec = Pe * BtuperWh; // electrical power during opration, Btuh
1766+ // wh_cycLossElec = 0.f; // electricity use per start, Btu
1767+ // unused in revised model 5-24-2017
17891768 return rc;
17901769} // DHWHEATER::wh_InstUEFInit
17911770// ----------------------------------------------------------------------------
@@ -1807,25 +1786,24 @@ RC DHWHEATER::wh_InstUEFDoSubhr(
18071786 // max( 1, dT) to prevent x/0
18081787 double drawLoss = xLoss / (8.345 *deltaT);
18091788
1810- #if 1
18111789 // max vol that can be heated in 1 tick
18121790 double drawFullLoad = wh_maxFlowX / deltaT;
18131791
1814- double volxBU = 0 .; // volume in excess of capacity, gal
1792+ double volxBU = 0 .; // volume in excess of capacity, gal
18151793 int nTickNZDraw = 0 ; // count of ticks with draw > 0
1816- double nTickRcov = 0 .; // fractional ticks of recovery operation
1794+ double nTickFullLoad = 0 .; // fractional ticks of equiv full load
18171795 int nTickStart = 0 ; // # of startup ticks (draw changes 0 -> nz)
18181796 for (int iT=0 ; !rc && iT<Top.tp_nSubhrTicks ; iT++)
18191797 {
18201798 double drawForTick = draw[ iT]*scale*wh_mixDownF + drawLoss; // gal
18211799 if (drawForTick > 0 .)
18221800 { nTickNZDraw++;
18231801 if (drawForTick > drawFullLoad)
1824- { nTickRcov += 1 .; // full-tick recovery
1802+ { nTickFullLoad += 1 .; // full capacity operation
18251803 volxBU += drawForTick - drawFullLoad; // excess demand, gal
18261804 }
18271805 else
1828- nTickRcov += drawForTick / drawFullLoad;
1806+ nTickFullLoad += drawForTick / drawFullLoad;
18291807 if (!wh_drawTicks++) // if no draw in prior tick
18301808 nTickStart++; // count start
18311809 }
@@ -1835,63 +1813,23 @@ RC DHWHEATER::wh_InstUEFDoSubhr(
18351813 }
18361814
18371815 double tickDurHr = Top.tp_subhrTickDur / 60 .; // tick duration, hr
1838- double rcovFuel = wh_maxInpX * nTickRcov ;
1816+ double rcovFuel = wh_maxInpX * nTickFullLoad ;
18391817 double startFuel = wh_cycLossFuel * nTickStart;
1840- double rcovElec = wh_operElec * nTickRcov * tickDurHr;
1841- double startElec = wh_cycLossElec * nTickStart;
1818+ double rcovElec = wh_operElec * nTickNZDraw * tickDurHr; // assume operation for entire tick with any draw
1819+ // double startElec = wh_cycLossElec * nTickStart; // unused in revised model
18421820 // standby in ticks w/o draw
18431821 double stbyElec = wh_stbyElec * (Top.tp_nSubhrTicks -nTickNZDraw) * tickDurHr;
18441822
18451823 wh_HPWHxBU = 8.345 * volxBU * deltaT;
18461824 // excess heating required to meet ws_tUse
1847- #else
1848- // max vol that can be heated in 1 tick
1849- // 67 = UEF temp rise
1850- double drawFullLoad = (67. / deltaT) * wh_ratedFlow * Top.tp_subhrTickDur;
18511825
1852- double volxBU = 0.; // volume in excess of capacity, gal
1853- int nTickNZDraw = 0; // count of ticks with draw > 0
1854- double nTickRcov = 0.; // fractional ticks of recovery operation
1855- int nTickStart = 0; // # of startup ticks (draw changes 0 -> nz)
1856- int justOn = 0;
1857- for (int iT=0; !rc && iT<Top.tp_nSubhrTicks; iT++)
1858- {
1859- double drawForTick = draw[ iT]*scale*wh_mixDownF + drawLoss; // gal
1860- if (drawForTick > 0.)
1861- { nTickNZDraw++;
1862- if (drawForTick > drawFullLoad)
1863- { nTickRcov += 1.; // full-tick recovery
1864- volxBU += drawForTick - drawFullLoad; // excess demand, gal
1865- }
1866- else
1867- nTickRcov += drawForTick / drawFullLoad;
1868- if (!wh_drawTicks++) // if no draw in prior tick
1869- nTickStart++; // count start
1870- }
1871- else
1872- // standby
1873- wh_drawTicks = 0; // reset draw duration
1874- }
1875-
1876- double tickDurHr = Top.tp_subhrTickDur / 60.; // tick duration, hr
1877- double rcovFuel = wh_ratedInput * nTickRcov * tickDurHr;
1878- double startFuel = wh_cycLossFuel * nTickStart * tickDurHr;
1879- double rcovElec = wh_operElec * nTickRcov * tickDurHr;
1880- double startElec = wh_cycLossElec * nTickStart * tickDurHr;
1881- // standby in ticks w/o draw
1882- double stbyElec = wh_stbyElec * (Top.tp_nSubhrTicks-nTickNZDraw) * tickDurHr;
1883-
1884- wh_HPWHxBU = 8.345 * volxBU * deltaT;
1885- // excess heating required to meet ws_tUse
1886- #endif
1887-
18881826 // energy use accounting, Btu
18891827 double inFuel = rcovFuel + startFuel;
18901828 wh_inFuel += inFuel;
18911829 if (wh_pMtrFuel)
1892- wh_pMtrFuel->H .dhw += mult * inFuel;
1830+ wh_pMtrFuel->H .dhw += mult * inFuel;
18931831
1894- double inElec = rcovElec + startElec + stbyElec + wh_parElec * Top.subhrDur * BtuperWh;
1832+ double inElec = rcovElec /* startElec*/ + ( stbyElec + wh_parElec * Top.subhrDur ) * BtuperWh;
18951833 double inElecBU = wh_HPWHxBU;
18961834 wh_inElec += inElec; // hour total
18971835 wh_inElecBU += inElecBU;
0 commit comments