Skip to content

Commit ccf6a48

Browse files
authored
Merge pull request #394 from cse-sim/dhwbal
DHWSYSRES rework and DHWSYS energy balance diagnostics
2 parents 27acf15 + 85ade1e commit ccf6a48

26 files changed

+2876
-1861
lines changed

src/CNRECS.DEF

Lines changed: 61 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,8 +1756,8 @@ RECORD DVRI "dvri" *hideall *RAT // Date-dependent Virtual Report Info -- at run
17561756
*prefix dv_
17571757
*exdes // cncult4.cpp. frees rpTitle
17581758
*ovrcopy
1759-
*declare "void dv_vpDHWMtrRow( RXPORTINFO *rxt, TI dhwMtri=-1);"
1760-
*declare "void dv_vpAfMtrRow( RXPORTINFO *rxt, TI afMtri=-1);"
1759+
*declare "void dv_vpDHWMtrRow( struct RXPORTINFO* rxt, TI dhwMtri=-1);"
1760+
*declare "void dv_vpAfMtrRow( struct RXPORTINFO* rxt, TI afMtri=-1);"
17611761
*declare "bool dv_IsReportActive( DOY jDay) const;"
17621762

17631763
// from inputs to RiB/XiB .ownTi is zone subscript or TI_SUM or ?TI_ALL.
@@ -2711,8 +2711,8 @@ RECORD ZNRES_IVL_SUB "zone interval results sub" *SUBSTRUCT // zone interval res
27112711

27122712
// CAUTION: when changing check carefully: cnguts.h, cnguts.cpp, cgenbal.cpp; grep for uses of ZRxxxx defines. 12-91.
27132713

2714-
*declare "double zr_TotAbsSen() const;"
2715-
*declare "double zr_TotAbsLat() const;"
2714+
*declare "double zr_SumAbsSen() const;"
2715+
*declare "double zr_SumAbsLat() const;"
27162716
*declare "void zr_Init1( int options=0, const ZNR* zp=NULL);"
27172717
*declare "void zr_Zero() { memset( this, 0, sizeof( ZNRES_IVL_SUB)); }" // 0 all (bitwise)
27182718

@@ -4022,40 +4022,35 @@ RECORD DHWSYSRES_IVL "DHWSYSRES interval sub" *SUBSTRUCT // interval substruct
40224022
*declare "void wsr_Copy( const DHWSYSRES_IVL* s, float mult=1.f);"
40234023
*declare "void wsr_Accum( const DHWSYSRES_IVL* sIvl, int firstFlg, int lastFlg);"
40244024
*declare "void wsr_AccumTick( const struct DHWTICK& tk, float tLpIn, float tCHDHWSupply=0.f);"
4025+
*declare "double wsr_SumAbs() const;"
4026+
*declare "float wsr_EnergyBalance();"
40254027
*declare "static const size_t wsr_NFLOAT;"
40264028

4027-
#if defined( DHWSYSRES_REV)
40284029
// energy (not fuel) exchanges with water, Btu
4029-
// values are for associated DHWSYS (wh_mult included, ws_mult not included)
4030-
// TODO: proposed sign convention -- everything wrt water except qLoad
4031-
*e FLOAT qLoad // hot water energy delivered to fixtures (> 0, opposite sign conv)
4032-
*e FLOAT qLoadHtg // space heating energy delivered, nz iff CHDHW (combined heat/DHW)
4033-
*e FLOAT qLoss // non-loop losses (jacket losses, T24DHW branch losses, )
4034-
*e FLOAT qLoop // DHWLOOP/DHWLOOPBRANCH losses
4035-
*e FLOAT qWHLoss // DHWHEATER tank loss (+ = to surround)
4036-
*e FLOAT qLHLoss // DHWLOOPHEATER tank loss (+ = to surround)
4037-
*e FLOAT qDWHR // drain water heat recovery
4038-
*e FLOAT qSSF // implied energy contribution from ws_SSF
4039-
*e FLOAT qSolar // DHWSOLARSYS contribution
4040-
*e FLOAT qWH // DHWHEATER primary (compressor, burner, )
4041-
*e FLOAT qLH // DHWLOOPHEATER primary
4042-
*e FLOAT qXBU // backup heating allocated to DHW
4043-
*e FLOAT qXBUHtg // backup heating allocated to space heating
4044-
// *e FLOAT qBal
4045-
#else
4046-
// water heating energy (not fuel), Btu
4047-
// values are for associated DHWSYS (wh_mult include, ws_mult not included)
4048-
*e FLOAT qLoad // hot water load (heat delivered to fixtures)
4049-
*e FLOAT qLoss // non-loop losses (jacket losses, T24DHW branch losses, )
4050-
*e FLOAT qLoop // DHWLOOP/DHWLOOPBRANCH losses
4051-
*e FLOAT qCHDHW // space heating energy, nz iff combined heat/DHW
4052-
*e FLOAT qDWHR // drain water heat recovery
4053-
*e FLOAT qSSF // implied energy contribution from ws_SSF
4054-
*e FLOAT qSolar // DHWSOLARSYS
4055-
*e FLOAT qWH // DHWHEATER primary (compressor, burner, )
4056-
*e FLOAT qLH // Loop heater primary
4057-
*e FLOAT qXBU // add'l backup heat
4058-
#endif
4030+
// values are for associated DHWSYS (wh_mult(s) included, ws_mult not included)
4031+
// CAUTION: code relies on mbr order, change with care
4032+
*e FLOAT qOutDHW // hot water energy delivered to fixtures, Btu (>=0, + = from DHWSYS)
4033+
*e FLOAT qOutHtg // space heating (CHDHW) energy delivered, Btu (>=0, + = from DHWSYS)
4034+
*e FLOAT qLossMisc // misc non-loop losses, Btu (DHWTANK losses, T24DHW branch losses, <= 0)
4035+
*e FLOAT qLossLoop // DHWLOOP/DHWLOOPBRANCH losses, Btu (+ = to DHWSYS, typically <= 0)
4036+
*e FLOAT qDWHR // heat added via drain water heat recovery (DWHR), Btu (+ = to DHWSYS, >= 0)
4037+
*e FLOAT qSSF // implied energy contribution from ws_SSF, Btu (+ = to DHWSYS, >= 0)
4038+
*e FLOAT qSolar // DHWSOLARSYS contribution, Btu (+ = to DHWSYS, >= 0)
4039+
*e *array 2 FLOAT qPrimary // DHWHEATER [0] or DHWLOOPHEATER [1] primary heat added, Btu
4040+
// (compressor, burner, resistance; + = to DHWSYS, >= 0)
4041+
*e *array 2 FLOAT qAux // DHWHEATER [0] or DHWLOOPHEATER [1] in-tank aux heat added, Btu
4042+
// (HPWH types only, + = to DHWSYS, >= 0)
4043+
*e *array 2 FLOAT qLoss // DHWHEATER [0] or DHWLOOPHEATER [1] tank loss, Btu
4044+
// (HPWH types only, + = to DHWSYS, typically <= 0)
4045+
*e *array 2 FLOAT qStorage // DHWHEATER [0] or DHWLOOPHEATER [1] change in tank heat content, Btu
4046+
// (HPWH types only, + = increase in tank temp)
4047+
*e *array 2 FLOAT qError // DHWHEATER [0] or DHWLOOPHEATER [1] HPWH internal heat balance error, Btu
4048+
// included in DHWSYSRES balance to hide HPWH unbalance
4049+
// pending investigation 5/2022
4050+
*e FLOAT qXBUDHW // extra backup heating allocated to DHW, Btu (+ = to DHWSYS, >= 0)
4051+
*e FLOAT qXBUHtg // extra backup heating allocated to space heating, Btu (+ = to DHWSYS, >= 0)
4052+
*e FLOAT qBal // sum of energy flows, Btu = (qOutDHW + qOutHtg) - Sum( everything else)
4053+
// s/b 0; >=0 means more output than input
40594054

40604055
*END // DHWSYSRES_IVL
40614056
//=============================================================================
@@ -4065,6 +4060,8 @@ RECORD DHWSYSRES "DHWSYSRES" *RAT // DHWSYSRES: interval results for DHWSYS
40654060
#if 0
40664061
*declare "void wsr_Accum( IVLCH ivl, int firstflg);"
40674062
#endif
4063+
*h *e INT wsr_ebErrCount // count of short-interval energy balance errors
4064+
// re limiting excessive msgs; see ::cgenbal()
40684065

40694066
// results: accumulated values for paired DHWSYS for each interval
40704067
// CAUTION: ordered for subscripting by IVLCH-1
@@ -4093,7 +4090,7 @@ RECORD SEGTOTS "segment totals" *SUBSTRUCT // aggregated segment info substruct
40934090

40944091
*END // SEGTOTS
40954092
//=============================================================================
4096-
RECORD DHWSYS "DHWSys" *RAT // input / runtime DHW system
4093+
RECORD DHWSYS "DHWSYS" *RAT // input / runtime DHW system
40974094
*prefix ws_
40984095
*exdes
40994096
*ovrcopy
@@ -4243,7 +4240,6 @@ RECORD DHWSYS "DHWSys" *RAT // input / runtime DHW system
42434240
*h FRAC_GZ ws_targetSoC; // target state of charge (SoC)
42444241
// used iff ws_drSignal == C_DHWDRMETH_SOC
42454242

4246-
*s *hide DBL ws_tOutPrimSum; // working var re ws_tOutPrimLT
42474243
*s *e FLOAT ws_tOutPrimLT; // primary water heater outlet temp, F
42484244
// for HPWH only, re DHWLOOPHEATER entering temp
42494245
// best estimate from prior 1-min tick
@@ -4419,11 +4415,10 @@ RECORD HPWHLINK "HPWHLink" *SUBSTRUCT // Ecotope's HPWH tank and heater
44194415
*declare "double hw_GetTankAvgTemp( int iNode0=0, int nNodes=999) const;"
44204416
*declare "double hw_GetEstimatedTOut() const;"
44214417
*declare "double hw_GetCHDHWTSupply() const;"
4422-
*declare "void hw_SetQTX( float qTX);"
44234418
*declare "RC hw_DoHour( float& tSetpoint, float targetSoC);"
44244419
*declare "RC hw_DoSubhrStart( float tEx, float tASHPSrc=-999.f);"
4425-
*declare "RC hw_DoSubhrTick( DHWTICK& tk, float tInlet, float scaleWH=1.f, float tMix=-1., float tMains=-1.f, float* pTOutNoMix=NULL, int drStatus=0);"
4426-
*declare "RC hw_DoSubhrTick( int iTk, float draw, float tInlet, float* pTOut, float scaleWH=1.f);"
4420+
*declare "RC hw_DoSubhrTick( DHWTICK& tk, int servesWhat, float tInlet, float& tOutlet, double& drawForTick, float scaleWH=1.f, float tMix=-1., float tMains=-1.f, int drStatus=0);"
4421+
*declare "RC hw_DoSubhrTick( int iTk, float draw, float qTX, float tInlet, float& tOutlet, float scaleWH=1.f);"
44274422
*declare "RC hw_DoSubhrEnd( float mult, ZNR* pZn, ZNR* pZnASHPSrc);"
44284423

44294424
*declare "record* hw_pOwner;" // owner (DHWHEATER, DHWSOLARSYS, ...)
@@ -4435,12 +4430,10 @@ RECORD HPWHLINK "HPWHLink" *SUBSTRUCT // Ecotope's HPWH tank and heater
44354430
*s FLOAT hw_tEx; // tank surround temp, F
44364431
*s FLOAT hw_tASHPSrc; // temp of heat pump air source, F
44374432

4438-
*s *e FLOAT_GEZ hw_qTXTick; // current tick extra tank heat added lower tank nodes, Btu
4439-
// used re e.g. solar water heating tanks
4440-
// note <0 (tank cooling) not supported
44414433
*r INT hw_nQTXNodes // # of tank 1/12s used in hw_qTX extra tank heat
44424434
// corresponds to nodes for HPWH default 12 node setup
4443-
*declare "std::vector< double>* hw_pNodePowerExtra_W;" // runtime extra tank heat linkage to HPWH
4435+
*declare "std::vector< double> hw_pNodePowerExtra_W;" // runtime extra tank heat linkage to HPWH
4436+
44444437
*h FLOAT hw_fMixUse; // factor for draw adjustment re HPWH setpoint > DHWSYS::ws_tUse
44454438
// Some HPWHs (e.g. Sanden) have fixed (high) setpoints
44464439
// draws are reduced to balance load at ws_tUse.
@@ -4449,8 +4442,11 @@ RECORD HPWHLINK "HPWHLink" *SUBSTRUCT // Ecotope's HPWH tank and heater
44494442
// Loop return flow is reduced to balance load at ws_tUse.
44504443

44514444
*s *e *array 2 DBL hw_inElec; // current subhr HPWH electricity use, kWh
4452-
// [0]=resistance backup (iff HP) (not including hw_HPWHxBU)
4453-
// [1]=primary(=compressor or non-HP resistance) + misc
4445+
// [0]=primary(=compressor or non-HP resistance) + misc
4446+
// [1]=resistance backup (iff HP) (not including hw_HPWHxBU)
4447+
*s *e *array 2 DBL hw_heatAdded; // current subhr HPWH heat added to water, kWh
4448+
// [0]=primary(=compressor or non-HP resistance)
4449+
// [1]=resistance backup (iff HP) (not including hw_HPWHxBU)
44544450
*s *e DBL hw_tOut; // last tick HPWH outlet temp, C
44554451
// 0 if no draw
44564452
*s *e DBL hw_tOutCHDHW; // last tick output temp available to CHDHW, F
@@ -4461,15 +4457,17 @@ RECORD HPWHLINK "HPWHLink" *SUBSTRUCT // Ecotope's HPWH tank and heater
44614457
// + = to water heater; for 1 DHWHEATER (no wh_mult)
44624458
*s *e DBL hw_qLoss; // current subhr HPWH standby losses, kWh. + = to surround
44634459
// for 1 DHWHEATER (no wh_mult)
4464-
*s *e DBL hw_qHW; // current subhr HPWH total hot water heating, kWh. always >= 0
4460+
*s *e DBL hw_qHW; // current subhr HPWH total delivered hot water heating, kWh. always >= 0
44654461
// for 1 DHWHEATER (no wh_mult)
4462+
// calc'd from flows and temp diffs (unlike hw_heatAdded)
44664463
// includes heat to DHWLOOP and CHDHW, does not include hw_HPWHxBU
4467-
*s *e DBL hw_qTX; // current subhr extra heat tank heat, kWh (not Btu)
4464+
*s *e DBL hw_qTX; // current subhr extra heat tank heat added, kWh (not Btu)
44684465

44694466
*h *e INT hw_tankTempSet; // nz iff HPWH tank temp has been initialized
44704467
*r FLOAT hw_tankHCNominal; // nominal HPWH tank heat content, kWh (at 40 C)
44714468
// used as normalizing factor for energy balance checks
4472-
*s *e DBL hw_tankHCStart; // current step starting tank heat content, kWh
4469+
*s *e DBL hw_tankHCBeg; // current step beginning tank heat content, kWh
4470+
*s *e DBL hw_tankHCEnd; // current step end tank heat content, kWh
44734471

44744472
*s *e DBL hw_tHWOutF; // current substep working total re calc of hw_tHWOut
44754473
*s *e INT hw_nzDrawCount; // current substep # of draws > 0
@@ -4480,6 +4478,7 @@ RECORD HPWHLINK "HPWHLink" *SUBSTRUCT // Ecotope's HPWH tank and heater
44804478
*h *e INT hw_bWriteCSV; // write HPWH debugging CSV iff nz
44814479
*declare "FILE* hw_pFCSV;" // file for debugging CSV (opened on 1st use)
44824480

4481+
*s *e DBl hw_qBal; // current step HPWH heat balance, kWh (s/b 0)
44834482
*s *e INT hw_balErrCount; // annual count of energy balance errors
44844483
*r *e DBL hw_balErrMax; // maximum substep energy balance error for run, kWh
44854484

@@ -4489,7 +4488,11 @@ RECORD HPWHLINK "HPWHLink" *SUBSTRUCT // Ecotope's HPWH tank and heater
44894488
RECORD DHWHEATER "DHWHeater" *RAT // input / runtime DHW heater
44904489
*prefix wh_
44914490

4492-
*exdes // *declare "~DHWHEATER;"
4491+
*excon // explicit constructor
4492+
*exdes // explicit ~DHWHEATER()
4493+
*ovrcopy // overide Copy()
4494+
*declare "virtual DHWHEATER& CopyFrom( const record* pSrc, int copyName=1, int dupPtrs=0);"
4495+
44934496
*declare "RC wh_CkF();"
44944497
*declare "virtual RC RunDup( const record* pSrc, int options=0);"
44954498
*declare "RC wh_Init();"
@@ -4508,16 +4511,15 @@ RECORD DHWHEATER "DHWHeater" *RAT // input / runtime DHW heater
45084511
*declare "bool wh_IsSameType( const DHWHEATER& wh) const;"
45094512
#endif
45104513
*declare "bool wh_CanHaveLoopReturn() const { return wh_IsHPWHModel(); }"
4511-
*declare "bool wh_CanHaveDHWLOOPHEATER() const { return wh_GetFunction()==whfcnPRIMARY && wh_IsHPWHModel(); }"
4514+
*declare "bool wh_CanHaveDHWLOOPHEATER() const { return wh_IsPrimary() && wh_IsHPWHModel(); }"
45124515
*declare "bool wh_IsInstUEFModel() const { return wh_type==C_WHTYPECH_INSTUEF; }"
45134516
*declare "bool wh_IsSubhrModel() const { return wh_IsHPWHModel() || wh_IsInstUEFModel(); }"
45144517
*declare "bool wh_UsesTSetpoint() const { return wh_IsHPWHModel(); }"
45154518
*declare "float wh_CalcLDEF( float arl, int options=0);"
4516-
*declare "RC wh_CanSupplyCHDHW() const;"
4517-
*declare "bool wh_SuppliesCHDHW() const;"
4519+
*declare "RC wh_SetupAsCHDHWSource();"
45184520
*declare "RC wh_DoHour();"
45194521
*declare "RC wh_DoSubhrStart();"
4520-
*declare "RC wh_DoSubhrTick( struct DHWTICK& tk, float scaleWH);"
4522+
*declare "RC wh_DoSubhrTick( struct DHWTICK& tk, float scaleWH, float tInlet, float& tOutlet);"
45214523
*declare "RC wh_InstUEFInit();"
45224524
*declare "RC wh_InstUEFDoSubhrTick( double draw, float tInletWH, float scaleWH, float tUse);"
45234525
*declare "RC wh_DoSubhrEnd( bool bIsLH);"
@@ -4545,10 +4547,11 @@ RECORD DHWHEATER "DHWHeater" *RAT // input / runtime DHW heater
45454547
*i ANAME wh_desc; // probe-able description text
45464548
*declare "virtual const char* GetDescription( int options=0) { options; return wh_desc; }"
45474549
*r INT wh_fcn; // function of this DHWHEATER per whfcnXXX enum
4548-
*declare "enum { whfcnUNKNOWN=0, whfcnPRIMARY, whfcnLOOPHEATER, whfcnCOUNT=whfcnLOOPHEATER, whfcnLASTHEATER=0x100 };"
4549-
*declare "int wh_GetFunction() const { return wh_fcn & 0xff; }"
4550+
*declare "enum { whfcnUNKNOWN=0, whfcnPRIMARY, whfcnLOOPHEATER, whfcnSUPPLIESCHDHW=0x10, whfcnSUPPLIESLOOP=0x20, whfcnSUPPLIESLOAD=0x40 };"
45504551
*declare "int wh_SetFunction();"
4551-
*declare "bool wh_IsLastHeater() const { return (wh_fcn & whfcnLASTHEATER) != 0; }"
4552+
*declare "bool wh_IsPrimary() const { return (wh_fcn & whfcnPRIMARY) != 0; };"
4553+
*declare "bool wh_IsLoopHeater() const { return (wh_fcn & whfcnLOOPHEATER) != 0; };"
4554+
45524555
*i WHASHPTYCH wh_ashpTy; // air source heat pump (HPWH) type, required iff wh_heatSrc=ASHPX, else ignored
45534556
// C_WHASHPTYCH_xxx, etc
45544557
*i WHRESTYCH wh_resTy; // resistance heater type, used iff wh_heatSrc=_ELRESX, else ignored
@@ -4787,6 +4790,7 @@ RECORD DHWHEATREC "DHWHeatRec" *RAT // input / runtime drain water heat recovery
47874790

47884791
*END
47894792
//=============================================================================
4793+
47904794
RECORD DHWTANK "DHWTank" *RAT // input / runtime unfired DHW tank
47914795
*prefix wt_
47924796

src/cgenbal.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ void cgenbal( // Check energy balances; issue warning message if out of toleran
4343
ZNRES_IVL_SUB* zrp = // zone results for interval to check
4444
&ZnresB.p[zp->ss].curr.Y - 1 + ivl // point ...curr.Y, .M, .D, .H
4545
- (ivl==C_IVLCH_S); // adjustment needed for _S cuz no .HS
46-
double zTot = zrp->zr_TotAbsSen();
46+
double zTot = zrp->zr_SumAbsSen();
4747
double zNet = zrp->qsBal; // get (float) net total from record, computed/accum in cnguts.cpp.
4848
ovNet += zNet;
4949
ovTot += zTot; // add zone to overall, checked at end
@@ -54,7 +54,7 @@ void cgenbal( // Check energy balances; issue warning message if out of toleran
5454
if (zp->zn_IsConvRad())
5555
{
5656
zNet = zrp->qlBal; // get (float) net latent total from record.
57-
zTot = zrp->zr_TotAbsLat();
57+
zTot = zrp->zr_SumAbsLat();
5858
ovNet += zNet;
5959
ovTot += zTot; // add zone to overall, checked at end
6060
int iSink = 0;
@@ -71,6 +71,22 @@ void cgenbal( // Check energy balances; issue warning message if out of toleran
7171
// check overall balance
7272
cgecheck( ovNet, ovTot, tol, .1, "overall", NULL, ivl, Top.tp_ebErrCount);
7373

74+
// DHWSYS balance
75+
float tolDHWSYS{ 0.01f };
76+
float absTolDHWSYS{ 20.f };
77+
if (ivl >= C_IVLCH_H)
78+
{ // short-interval errors common, use sloppy tolerences
79+
tolDHWSYS = 0.20;
80+
absTolDHWSYS = 100.f;
81+
}
82+
DHWSYSRES* pWS;
83+
RLUP(WsResR, pWS)
84+
{ const DHWSYSRES_IVL* pWSL = &pWS->Y + ivl - 1;
85+
double wsTot = pWSL->wsr_SumAbs();
86+
double wsNet = pWSL->qBal;
87+
cgecheck(wsNet, wsTot, tolDHWSYS, absTolDHWSYS, "DHWSYS '%s'", pWS->name, ivl,
88+
pWS->wsr_ebErrCount);
89+
}
7490
#endif
7591
} // cgenbal
7692
//-----------------------------------------------------------------------------
@@ -154,7 +170,7 @@ const int balErrCountWarnMax = 20; // max # of short-interval errors to report
154170
: net==0. ? 0. : 1.; // if tot is 0, force error unless net is 0 too.
155171

156172
// check balance
157-
int bBalOK = errf <= tol || fabs(net) <= absTol; // never complain about
173+
bool bBalOK = errf <= tol || fabs(net) <= absTol; // never complain about
158174
if (bBalOK && !Top.tp_IsLastStep())
159175
return RCOK; // balance OK and not end of run
160176

0 commit comments

Comments
 (0)