diff --git a/src/CNRECS.DEF b/src/CNRECS.DEF index 7a9543975..ef5415773 100644 --- a/src/CNRECS.DEF +++ b/src/CNRECS.DEF @@ -4116,6 +4116,10 @@ RECORD DHWSYSRES_IVL "DHWSYSRES interval sub" *SUBSTRUCT // interval substruct RECORD DHWSYSRES "DHWSYSRES" *RAT // DHWSYSRES: interval results for DHWSYS *declare "RC wsr_Init( IVLCH ivl=-1);" + *declare "const DHWSYS* wsr_GetDHWSYS() const;" + *declare "bool wsr_IsSumOf() const { return ss == b->n; }" + *declare "enum WSRCHK { wsrchkCHILD=1, wsrchkSUMOF, wsrchkLOOSE, wsrchkTIGHT };" + *declare "WSRCHK wsr_BalChkCase() const;" #if 0 *declare "void wsr_Accum( IVLCH ivl, int firstflg);" #endif diff --git a/src/cgenbal.cpp b/src/cgenbal.cpp index 2f8443a4a..1309cda62 100644 --- a/src/cgenbal.cpp +++ b/src/cgenbal.cpp @@ -76,23 +76,39 @@ void cgenbal( // Check energy balances; issue warning message if out of toleran // Known causes: // 1) instantaneous DHWHEATER load carry-forward // 2) HPWH internal balance errors (?) + if (ivl <= C_IVLCH_H) // if hour or longer { - float tolDHWSYS{ 0.01f }; - float absTolDHWSYS{ 20.f }; - if (ivl == C_IVLCH_H) - { // short-interval errors common, use sloppy tolerences - tolDHWSYS = 0.10; - absTolDHWSYS = 100.f; - } - DHWSYSRES* pWS; - RLUP(WsResR, pWS) + static constexpr float fTol[] = { 0.01f, 0.10f }; + static constexpr float absTol[] = { 20.f, 100.f }; + + int checkCount = 0; // count of checks performed + int iTol{ 0 }; // tolerance idx 0=tight, 1=loose + // prior iteration needed for SUMOF + DHWSYSRES* pWSR; + RLUP(WsResR, pWSR) { - const DHWSYSRES_IVL* pWSL = &pWS->Y + ivl - 1; + // eyeball current situation -- avoid duplicate and spurious msgs + DHWSYSRES::WSRCHK balChkCase = pWSR->wsr_BalChkCase(); + if (balChkCase == DHWSYSRES::wsrchkCHILD + || (balChkCase == DHWSYSRES::wsrchkSUMOF && checkCount <= 1)) + continue; // no check if child (no DHWHEATER, check not meaningful) + // no check if sum_of with single source (sum_of record identical to source) + + ++checkCount; + + // iTol: 0=tight, 1=loose + // loose for PreRun and C_IVLCH_H (bigger errors common) + // tight for Simulate and daily/month/year + // use prior value for SUMOF + if (balChkCase != DHWSYSRES::wsrchkSUMOF) + iTol = balChkCase == DHWSYSRES::wsrchkLOOSE || ivl == C_IVLCH_H; + + const DHWSYSRES_IVL* pWSL = &pWSR->Y + ivl - 1; double wsTot = pWSL->wsr_SumAbs(); double wsNet = pWSL->qBal; - cgecheck(wsNet, wsTot, tolDHWSYS, absTolDHWSYS, "DHWSYS '%s'", pWS->Name(), ivl, - pWS->wsr_ebErrCount); + cgecheck(wsNet, wsTot, fTol[ iTol], absTol[ iTol], "DHWSYS '%s'", pWSR->Name(), ivl, + pWSR->wsr_ebErrCount); } } #endif // SUPPRESS_ENBAL_CHECKS diff --git a/src/dhwcalc.cpp b/src/dhwcalc.cpp index 76db87c95..60f9cdc49 100644 --- a/src/dhwcalc.cpp +++ b/src/dhwcalc.cpp @@ -2454,6 +2454,31 @@ RC DHWSYSRES::wsr_Init( // init (set to 0) return rc; } // DHWSYSRES::wsr_Init //----------------------------------------------------------------------------- +const DHWSYS* DHWSYSRES::wsr_GetDHWSYS() const +{ return WsR.GetAtSafe(ss); +} // DHWSYSRES::wsr_GetDHWSYS +//----------------------------------------------------------------------------- +DHWSYSRES::WSRCHK DHWSYSRES::wsr_BalChkCase() const // how to balance check this DHWSYSRES +// returns wsrchkSUMOF: sum-of record, special case +// wsrchkCHILD: child DHWSYS (no heater), no check +// wsrchkLOOSE: pre-run underway, use loose tolerance +// wsrchkTIGHT: simulation underway, use tight tolerance + +{ + WSRCHK ret{ wsrchkTIGHT }; + const DHWSYS* pWS = wsr_GetDHWSYS(); + if (!pWS) + { + assert(wsr_IsSumOf()); + ret = wsrchkSUMOF; + } + else if (pWS->ws_HasCentralDHWSYS()) + ret = wsrchkCHILD; + else if (pWS->ws_calcMode!=C_WSCALCMODECH_SIM) + ret = wsrchkLOOSE; + return ret; +} // wsr_BalChkCase +//----------------------------------------------------------------------------- #if 0 void DHWSYSRES::wsr_Accum( IVLCH ivl, // destination interval: hour/day/month/year. @@ -3875,7 +3900,7 @@ RC HPWHLINK::hw_DoSubhrTick( // calcs for 1 tick #else WStr s("mon,day,hr,"); s += csvGen.cg_Hdgs(dumpUx); - // hw_pHPWH->WriteCSVHeading(hw_pFCSV, s.c_str(), nTCouples, hpwhOptions); + hw_pHPWH->writeCSVHeading(*hw_pFCSV, s.c_str(), nTCouples, hpwhOptions); #endif } } @@ -3887,7 +3912,7 @@ RC HPWHLINK::hw_DoSubhrTick( // calcs for 1 tick WStr s = strtprintf("%d,%d,%d,", Top.tp_date.month, Top.tp_date.mday, Top.iHr + 1); s += csvGen.cg_Values(dumpUx); - //hw_pHPWH->WriteCSVRow(*hw_pFCSV, s.c_str(), nTCouples, hpwhOptions); + hw_pHPWH->writeCSVRow(*hw_pFCSV, s.c_str(), nTCouples, hpwhOptions); #endif } } diff --git a/vendor/HPWHsim b/vendor/HPWHsim index dd09e5aac..e4c8d6895 160000 --- a/vendor/HPWHsim +++ b/vendor/HPWHsim @@ -1 +1 @@ -Subproject commit dd09e5aac7109788f67cb363785268675e4ea478 +Subproject commit e4c8d6895e50ca4444a8e55a05bbf19b40b55b90