From 0be93418e33c326ff4a310ea22dc22cbf053c1e4 Mon Sep 17 00:00:00 2001 From: Chip Barnaby Date: Tue, 6 Oct 2020 11:16:12 -0400 Subject: [PATCH] IZ flow accounting bug fix --- src/CGCOMP.CPP | 62 ++++++++++++++++++++++++++++++-------------------- src/CNCULT.CPP | 2 +- src/CNRECS.DEF | 12 ++++++---- 3 files changed, 46 insertions(+), 30 deletions(-) diff --git a/src/CGCOMP.CPP b/src/CGCOMP.CPP index 9e9487da9..446dac045 100644 --- a/src/CGCOMP.CPP +++ b/src/CGCOMP.CPP @@ -877,7 +877,7 @@ RC IZXRAT::iz_CkfIZXFER() // input checks } if (!iz_CanHaveAFCat()) - ignore(IZXRAT_AFCAT, when); + ignore(IZXRAT_AFCATI, when); // horizontal opening // stairangle defaults @@ -1048,16 +1048,13 @@ x } //------------------------------------------------------------------- void IZXRAT::iz_SetupAfMtrs() { - // Air flow category - if (!iz_CanHaveAFCat()) - iz_afCat = C_AFCAT_NONE; - else if (!IsSet(IZXRAT_AFCAT)) - iz_afCat = iz_AfCatDefault(); // default category (may return -1) + // Air flow categories (set iz_afMtrCat1 and iz_afMtrCat2) + iz_AfMtrCats(); // AFMTR ptrs: NULL if no meter specified -> no air flow accounting // one pointer for positive flows, one for negative iz_pAfMtr1 = iz_pAfMtr2 = NULL; // insurance - if (iz_afCat != C_AFCAT_NONE) + if (iz_afMtrCat1 != C_AFCAT_NONE) { // set up ptrs to AFMTR(s) const ZNR* zp; if (iz_zi1 > 0) @@ -1081,41 +1078,56 @@ void IZXRAT::iz_SetupAfMtrs() } // IZXRAT::iz_SetupAfMtrs //----------------------------------------------------------------------------- -BOOL IZXRAT::iz_IsIZUZ() const // true iff interzone connected to unconditioned +int IZXRAT::iz_IsCZ( // detect conditioned / unconditioned adjacent zones + int iZn) const // 1: check inside zone, else checkout outside +// returns -1 (does not exist), 0=unconditioned, 1=conditioned { - const ZNR* zp = ZrB.GetAtSafe(iz_zi2); - return zp && zp->zn_IsUZ(); + int zi = iZn==1 ? iz_zi1 : iz_zi2; + const ZNR* zp = ZrB.GetAtSafe( zi); + return !zp ? -1 : !zp->zn_IsUZ(); -} // IZXRAT::iz_IsIZUZ +} // IZXRAT::iz_IsCZ //----------------------------------------------------------------------------- -AFCAT IZXRAT::iz_AfCatDefault() const +void IZXRAT::iz_AfMtrCats() // finalize runtime air flow categories +// Tricky: interzone flow UZ/CZ categories differ depending on side of vent { - AFCAT afCat; + iz_afMtrCat1 = iz_afMtrCat2 = -1; // flag as unset if (!iz_CanHaveAFCat()) - afCat = C_AFCAT_NONE; // not trackable + iz_afMtrCat1 = C_AFCAT_NONE; // not trackable + else if (IsSet(IZXRAT_AFCATI)) + iz_afMtrCat1 = iz_afCatI; // use user input (not checked for consistency with IZXRAT type) else if (iz_IsSysAir()) - afCat = C_AFCAT_HVAC; + iz_afMtrCat1 = C_AFCAT_HVAC; else if (iz_IsDuctLk()) - afCat = C_AFCAT_DUCTLK; + iz_afMtrCat1 = C_AFCAT_DUCTLK; else if (iz_IsHERV()) - afCat = C_AFCAT_FANEX; + iz_afMtrCat1 = C_AFCAT_FANEX; else { const static int afCats[3][3] = - { { C_AFCAT_FANEX, C_AFCAT_VNTEX, C_AFCAT_INFEX }, + { { C_AFCAT_FANEX, C_AFCAT_VNTEX, C_AFCAT_INFEX }, { C_AFCAT_FANUZ, C_AFCAT_VNTUZ, C_AFCAT_INFUZ }, { C_AFCAT_FANCZ, C_AFCAT_VNTCZ, C_AFCAT_INFCZ } }; + // fan / vent / infil // Note: vent guess is approx, explicit izAFCat input may be necessary int izMode = iz_IsFixedFlow() ? 0 : iz_MightBeNatVent() ? 1 : 2; - // exterior / uncond zone / cond zone - int izLoc = iz_IsExterior() ? 0 : iz_IsIZUZ() ? 1 : 2; - afCat = afCats[izLoc][izMode]; + if (iz_IsExterior()) + iz_afMtrCat1 = afCats[0][izMode]; + else + { // interzone: set category per *other* side + // iz_IsCZ() returns -1 (no zone, not expected), 0 (uncond), 1 (cond) + int iCZ1 = iz_IsCZ(1); // inside + int iCZ2 = iz_IsCZ(2); // outside + iz_afMtrCat1 = afCats[iCZ2 + 1][izMode]; + iz_afMtrCat2 = afCats[iCZ1 + 1][izMode]; + } } - return afCat; + if (iz_afMtrCat2 < 0) + iz_afMtrCat2 = iz_afMtrCat1; -} // IZXRAT::iz_AfcatDefault +} // IZXRAT::iz_AfMtrCats //----------------------------------------------------------------------------- RC IZXRAT::iz_SetupNonAirNet() // interzone transfer one-time initialization @@ -1565,12 +1577,12 @@ RC IZXRAT::iz_EndSubhr() // end-of-subhour vent calcs += (1.f - fVent)*iz_ad[0].ad_mdotB + fVent * iz_ad[1].ad_mdotB; if (iz_doingAfMtr && iz_amfNom != 0.f) { if (iz_pAfMtr1) - iz_pAfMtr1->amt_AccumCat(iz_afCat, iz_amfNom); + iz_pAfMtr1->amt_AccumCat(iz_afMtrCat1, iz_amfNom); if (iz_pAfMtr2) { // flow is opposite direction from z2 POV // HERV: iz_pAfMtr2 points to exhaust source zone (may be z1) // HERV same for vent / no vent (use iz_ad[ 0] w/o fVent) - iz_pAfMtr2->amt_AccumCat(iz_afCat, + iz_pAfMtr2->amt_AccumCat(iz_afMtrCat2, iz_IsHERV() ? -iz_ad[0].ad_mdotX : -iz_amfNom); } } diff --git a/src/CNCULT.CPP b/src/CNCULT.CPP index 1289911ee..a46953aac 100644 --- a/src/CNCULT.CPP +++ b/src/CNCULT.CPP @@ -1533,7 +1533,7 @@ CULT( "izZn1", DAT, IZXRAT_ZI1, RQD, 0, VEOI, TYREF, &ZiB, 0.f, CULT( "izZn2", DAT, IZXRAT_ZI2, 0, 0, VEOI, TYREF, &ZiB, 0.f, N, N), CULT( "izHConst", DAT, IZXRAT_UA, 0, 0, VHRLY, TYFL, 0, 0.f, N, N), CULT( "izNVType", DAT, IZXRAT_NVCNTRL,0, 0, VEOI, TYCH, 0, C_IZNVTYCH_NONE, N, N), -CULT( "izAFCat", DAT, IZXRAT_AFCAT, 0, 0, VEOI, TYCH, 0, 0, N, N), +CULT( "izAFCat", DAT, IZXRAT_AFCATI, 0, 0, VEOI, TYCH, 0, 0, N, N), CULT( "izALo", DAT, IZXRAT_A1, 0, 0, VHRLY, TYFL, 0, 0.f, N, N), CULT( "izAHi", DAT, IZXRAT_A2, 0, 0, VHRLY, TYFL, 0, 0.f, N, N), CULT( "izL1", DAT, IZXRAT_L1, 0, 0, VEOI, TYFL, 0, 0.f, N, N), diff --git a/src/CNRECS.DEF b/src/CNRECS.DEF index 007af891f..e151f1e06 100644 --- a/src/CNRECS.DEF +++ b/src/CNRECS.DEF @@ -2771,7 +2771,7 @@ RECORD IZXRAT "izXfer" *RAT // interzone heat transfers: conductive and/or vent. *declare "RC iz_CkfIZXFER();" *declare "void iz_ClearResults( int iV);" *declare "RC iz_Setup( IZXRAT* izie);" - *declare "AFCAT iz_AfCatDefault() const;" + *declare "void iz_AfMtrCats();" *declare "void iz_SetupAfMtrs();" *declare "RC iz_SetupNonAirNet();" *declare "bool iz_HasVentEffect() const;" @@ -2794,7 +2794,7 @@ RECORD IZXRAT "izXfer" *RAT // interzone heat transfers: conductive and/or vent. *declare "BOOL iz_IsAirNetIZ() const { return iz_nvcntrl == C_IZNVTYCH_ANIZ || iz_nvcntrl == C_IZNVTYCH_ANIZFAN || iz_nvcntrl == C_IZNVTYCH_ANIZFLOW || iz_nvcntrl == C_IZNVTYCH_ANHORIZ || iz_IsHERVIZ(); }" *declare "BOOL iz_IsHERV() const { return iz_nvcntrl == C_IZNVTYCH_ANHERV; }" *declare "BOOL iz_IsHERVIZ() const { return iz_IsHERV() && iz_zi2 != 0 && iz_zi1 != iz_zi2; }" - *declare "BOOL iz_IsIZUZ() const;" + *declare "int iz_IsCZ( int iZn) const;" *declare "BOOL iz_IsFan() const { return iz_nvcntrl == C_IZNVTYCH_ANIZFAN || iz_nvcntrl == C_IZNVTYCH_ANEXTFAN; }" *declare "BOOL iz_HasFan() const { return iz_IsFan() || iz_IsHERV(); }" *declare "BOOL iz_IsFlow() const { return iz_nvcntrl == C_IZNVTYCH_ANIZFLOW || iz_nvcntrl == C_IZNVTYCH_ANEXTFLOW; }" @@ -2831,14 +2831,18 @@ RECORD IZXRAT "izXfer" *RAT // interzone heat transfers: conductive and/or vent. // C_IZNVTYCH_ANSYSAIR: system air flow // C_IZNVTYCH_ANOAVRLF: RSYS OAV relief air // ( = interzone hole sized per flow) - *r AFCAT iz_afCat // air flow category (accounting only) C_AFCAT_xxx - // or 0 = unknown or -1 = not tracked + *r AFCAT iz_afCatI // air flow input category (accounting only) C_AFCAT_xxx + // or 0 = unknown + // resolved to iz_afMtrCat1 and iz_afMtrCat2 for runtime // AFMTR pointers, derived from zone zn_afMtri // NULL if not specified or same on both sides of IZ type *declare "AFMTR* iz_pAfMtr1;" // for iz_zn1 *declare "AFMTR* iz_pAfMtr2;" // for iz_zn2 *declare "bool iz_doingAfMtr;" // true iff iz_pAfMtr1 or iz_pAfMtr2 != NULL + // runtime air flow categories re UZ/CZ distinction for IZ flow + *r SI iz_afMtrCat1 // ... for iz_pAfMtr1 + *r SI iz_afMtrCat2 // ... for iz_pAfMtr2 *h AREA_GEZ iz_a1 // vent area 1, ft2 // _TWOWAY = low vent area