Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 82 additions & 48 deletions src/CGCOMP.CPP
Original file line number Diff line number Diff line change
Expand Up @@ -265,27 +265,40 @@ float TOPRAT::tp_WindPresV( // wind velocity pressure
// NAFCATS s/b same as AFCAT choices + 1 (for total)
static_assert(AFMTR_IVL::NAFCATS == C_AFCAT_COUNT+1, "Inconsistent AFMTR constants");
//-----------------------------------------------------------------------------
void AFMTR_IVL::amt_Copy(
const AFMTR_IVL* s)
void AFMTR_IVL::amt_Copy( // copy
const AFMTR_IVL* sIvl, // source
float mult /*=1.f*/) // optional multiplier
{
memcpy(this, s, sizeof(AFMTR_IVL));
if (mult == 1.f)
memcpy(this, sIvl, sizeof(AFMTR_IVL));
else
{ amt_count = sIvl->amt_count;
VCopy(&amt_total, NAFCATS, &sIvl->amt_total, double(mult));
}
} // AFMTR_IVL::amt_Copy
//-----------------------------------------------------------------------------
void AFMTR_IVL::amt_Accum( // accumulate
const AFMTR_IVL* sIvl, // source
int firstFlg, // true iff first accum into this (beg of ivl)
int lastFlg) // true iff last accum into this (end of ivl)

int lastFlg, // true iff last accum into this (end of ivl)
int options /*=0*/) // option bits
// 1: use sIvl.amt_count to scale totals
// effectively averages by day for annual values
// 2: sum only (do not average)
{
int count = (options & 1) ? sIvl->amt_count : 1;
if (firstFlg)
{ amt_Copy(sIvl);
amt_count = 1;
{ amt_Copy(sIvl, float( count));
amt_count = count;
}
else
{ VAccum(&amt_total, NAFCATS, &sIvl->amt_total);
amt_count++;
{ VAccum(&amt_total, NAFCATS, &sIvl->amt_total, float( count));
amt_count += count;
}
if (lastFlg)

// average unless caller says don't
// Note: VMul1() nops if amt_count==1
if (lastFlg && !(options & 2))
VMul1(&amt_total, NAFCATS, 1.f / amt_count);
} // AFMTR_IVL
//-----------------------------------------------------------------------------
Expand All @@ -296,33 +309,51 @@ RC AFMTR::amt_CkF()
//-----------------------------------------------------------------------------
RC AFMTR::amt_BegSubhr() // init at beg of subhr
{
S.amt_Clear();
S[ 0].amt_Clear();
S[ 1].amt_Clear();
return RCOK;
} // AFMTR::amt_BegSubhr
//-----------------------------------------------------------------------------
void AFMTR::amt_AccumCat( // accumulate air flow value for current subhour
AFCAT afCat, // air flow category
float amf) // air mass flow, lbm/sec
{
if (amf > 0.f) // record only flow into zone
{ // convert lbm/s -> cfm std air
S.amt_AccumCat(afCat, AMFtoAVF2( amf));
}
int iNeg = amf < 0.f;
S[ iNeg].amt_AccumCat(afCat, AMFtoAVF2(amf));
} // AFMTR::amt_AccumCat
//-----------------------------------------------------------------------------
AFMTR_IVL* AFMTR::amt_GetAFMTR_IVL(
IVLCH ivl, // interval
int iPN /*=0*/) // flow direction 0: pos (in), 1: neg (out)
{
return Y + 2 * (ivl - C_IVLCH_Y) + iPN;
}
//-----------------------------------------------------------------------------
void AFMTR::amt_Accum(
IVLCH ivl, // destination interval: hour/day/month/year
// Accumulates from subhour/day/month. Not Top.ivl!
int firstFlg, // iff TRUE, destination will be initialized before values are accumulated into it
int lastFlg) // iff TRUE, destination averages will be computed as needed
{
AFMTR_IVL* dIvl = &Y + (ivl - C_IVLCH_Y); // point destination substruct for interval
// ASSUMES interval members ordered like DTIVLCH choices
AFMTR_IVL* sIvl = dIvl + 1; // source: next shorter interval
AFMTR_IVL* dIvl0 = amt_GetAFMTR_IVL( ivl); // point destination substruct for interval
// ASSUMES interval members ordered like DTIVLCH choices
AFMTR_IVL* sIvl0 = amt_GetAFMTR_IVL(ivl + 1); // source: next shorter interval

int options = 0; // default: track average

// accumulate: copy on first call (in lieu of 0'ing dIvl).
// Note: amt_Init() call in doBegIvl 0s H values
dIvl->amt_Accum(sIvl, firstFlg, lastFlg);
if (ivl == C_IVLCH_Y)
options = 1; // average by day for non-sum-of year values
// handles diffs due to month length
for (int iPN=0; iPN<2; iPN++)
dIvl0[ iPN].amt_Accum(sIvl0+iPN, firstFlg, lastFlg, options);

if (lastFlg)
{
AFMTR* pAMSum = AfMtrR.p + AfMtrR.n;
AFMTR_IVL* dIvlSum0 = pAMSum->amt_GetAFMTR_IVL( ivl);
for (int iPN = 0; iPN < 2; iPN++)
dIvlSum0[ iPN].amt_Accum(dIvl0+iPN, ss == 1, 0);
}
} // AFMTR::amt_Accum
//=============================================================================

Expand Down Expand Up @@ -518,23 +549,13 @@ double ZNR::zn_Rho0() const // zone air density
// returns moist air density lb/ft3 at nominal z=0 for current zone conditions
// Note: not *dry* air
{
#if 1 // air density rework, 10-18-2012
double rho = psyDenMoistAir( tz, wz, LbSfToInHg( zn_pz0));
if (rho < .0001)
{ err( WRN, "Zone '%s', %s: moist air density <= 0\n",
name, Top.When( C_IVLCH_S));
rho = 0.01; // set to small but physically possible value
}
return rho;
#elif 1
x double rho1 = psyDenMoistAir( tz, wz, LbSfToInHg( zn_pz0));
x double rho2 = psyDensity( tz, wz, LbSfToInHg( zn_pz0));
x if (FEQX( rho1, rho2) > .001)
x printf( "Mismatch\n");
x return rho2;
#else
x return psyDensity( tz, wz, LbSfToInHg( zn_pz0));
#endif
} // ZNR::zn_Rho0
//------------------------------------------------------------------------------
void ZNR::zn_AccumAirFlow( // accumulate zone bal values due to air flow
Expand Down Expand Up @@ -1034,15 +1055,28 @@ void IZXRAT::iz_SetupAfMtrs()

// AFMTR ptrs: NULL if no meter specified -> no air flow accounting
// one pointer for positive flows, one for negative
const ZNR* zp;
if (iz_zi1 > 0)
{ zp = ZrB.GetAt(iz_zi1);
iz_pPosAfMtr = AfMtrR.GetAtSafe(zp->i.zn_afMtri);
}
if (iz_zi2 > 0)
{ zp = ZrB.GetAt(iz_zi2);
iz_pNegAfMtr = AfMtrR.GetAtSafe(zp->i.zn_afMtri);
iz_pAfMtr1 = iz_pAfMtr2 = NULL; // insurance
if (iz_afCat > 0)
{ // set up ptrs to AFMTR(s)
const ZNR* zp;
if (iz_zi1 > 0)
{ zp = ZrB.GetAt(iz_zi1);
iz_pAfMtr1 = AfMtrR.GetAtSafe(zp->i.zn_afMtri);
}
if (iz_zi2 > 0)
{ // interzone transfers recorded iff to a different meter
zp = ZrB.GetAt(iz_zi2);
AFMTR* pAM = AfMtrR.GetAtSafe(zp->i.zn_afMtri);
if (pAM == iz_pAfMtr1)
iz_pAfMtr1 = NULL; // same meter on both sides of IZ
// don't record IZ within meter
else
iz_pAfMtr2 = pAM; // z2 meter specified and differs from z1
}
}
iz_doingAfMtr // say this IZXRAT has AFMTR (speedier test)
= iz_pAfMtr1 != NULL || iz_pAfMtr2 != NULL;

} // IZXRAT::iz_SetupAfMtrs
//-----------------------------------------------------------------------------
AFCAT IZXRAT::iz_AfCatDefault() const
Expand All @@ -1061,8 +1095,10 @@ AFCAT IZXRAT::iz_AfCatDefault() const
else
{ if (iz_IsFixedFlow())
afCat = C_AFCAT_FANIZ;
else
else if (iz_IsAirNet())
afCat = C_AFCAT_INFILIZ;
else
afCat = 0;
}

return afCat;
Expand Down Expand Up @@ -1505,14 +1541,12 @@ RC IZXRAT::iz_EndSubhr() // end-of-subhour vent calcs
if (iz_nvcntrl == C_IZNVTYCH_ANHORIZ)
iz_amfNom
+= (1.f - fVent)*iz_ad[0].ad_mdotB + fVent * iz_ad[1].ad_mdotB;
if (iz_amfNom > 0.f)
{ if (iz_pPosAfMtr)
iz_pPosAfMtr->amt_AccumCat(iz_afCat, iz_amfNom);
}
else if (iz_amfNom < 0.f)
{ // flow is out of zn1 = into zn2
if (iz_pNegAfMtr)
iz_pNegAfMtr->amt_AccumCat(iz_afCat, -iz_amfNom);
if (iz_doingAfMtr && iz_amfNom != 0.f)
{ if (iz_pAfMtr1)
iz_pAfMtr1->amt_AccumCat(iz_afCat, iz_amfNom);
if (iz_pAfMtr2)
// flow is opposite direction from z2 POV
iz_pAfMtr2->amt_AccumCat(iz_afCat, -iz_amfNom);
}

return RCOK;
Expand Down
49 changes: 31 additions & 18 deletions src/CGRESULT.CPP
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,9 @@ static COLDEF wMtrColdef[] =
#undef oWMtr

// columns definition for "Airflow meter" (AFMTR) report/export
#define oAFMtr(m) offsetof( AFMTR_IVL, m)
#define D 3 // decimal digits
#define oAFMt0(m) offsetof( AFMTR_IVL, m)
#define oAFMt1(m) (offsetof( AFMTR_IVL, m)+sizeof( AFMTR_IVL))
#define D 1 // decimal digits
static COLDEF afMtrColdef[] =
/* max offset cvflag */
/* colhd flags wid dfw (cnguts.h) (above) */
Expand All @@ -247,21 +248,31 @@ static COLDEF afMtrColdef[] =
{ "Day", 8 | 4, 2, 0, USE_NEXT_ARG, CVI },
{ "Hr", 8 | 4, 2, 0, USE_NEXT_ARG, CVI },
{ "Subhr", 8 | 4, 1, 0, USE_NEXT_ARG, CVS }, // ..
{ "Total", 0, 7, D, oAFMtr(amt_total), CV1 },
{ "Unknown", 0, 7, D, oAFMtr(amt_unknown),CV1 },
{ "InfilEx", 0, 7, D, oAFMtr(amt_infilEx),CV1 },
{ "VentEx", 0, 7, D, oAFMtr(amt_ventEx), CV1 },
{ "FanEx", 0, 7, D, oAFMtr(amt_fanEx), CV1 },
{ "InfilIz", 0, 7, D, oAFMtr(amt_infilIz),CV1 },
{ "VentIz", 0, 7, D, oAFMtr(amt_ventIz), CV1 },
{ "FanIz", 0, 7, D, oAFMtr(amt_fanIz), CV1 },
{ "DuctLk", 0, 7, D, oAFMtr(amt_ductLk), CV1 },
{ "HVAC", 0, 7, D, oAFMtr(amt_hvac), CV1 },
{ "Tot+", 0, 5, D, oAFMt0(amt_total), CV1 },
{ "Unkn+", 0, 5, D, oAFMt0(amt_unknown),CV1 },
{ "InfX+", 0, 5, D, oAFMt0(amt_infilEx),CV1 },
{ "VntX+", 0, 5, D, oAFMt0(amt_ventEx), CV1 },
{ "FanX+", 0, 5, D, oAFMt0(amt_fanEx), CV1 },
{ "InfZ+", 0, 5, D, oAFMt0(amt_infilIz),CV1 },
{ "VntZ+", 0, 5, D, oAFMt0(amt_ventIz), CV1 },
{ "FanZ+", 0, 5, D, oAFMt0(amt_fanIz), CV1 },
{ "Duct+", 0, 5, D, oAFMt0(amt_ductLk), CV1 },
{ "HVAC+", 0, 5, D, oAFMt0(amt_hvac), CV1 },
{ "Tot-", 0, 5, D, oAFMt1(amt_total), CV1 },
{ "Unkn-", 0, 5, D, oAFMt1(amt_unknown),CV1 },
{ "InfX-", 0, 5, D, oAFMt1(amt_infilEx),CV1 },
{ "VntX-", 0, 5, D, oAFMt1(amt_ventEx), CV1 },
{ "FanX-", 0, 5, D, oAFMt1(amt_fanEx), CV1 },
{ "InfZ-", 0, 5, D, oAFMt1(amt_infilIz),CV1 },
{ "VntZ-", 0, 5, D, oAFMt1(amt_ventIz), CV1 },
{ "FanZ-", 0, 5, D, oAFMt1(amt_fanIz), CV1 },
{ "Duct-", 0, 5, D, oAFMt1(amt_ductLk), CV1 },
{ "HVAC-", 0, 5, D, oAFMt1(amt_hvac), CV1 },
{ 0, 0, 0, 0, 0, CV1 }
};
#undef D
#undef oAFMtr

#undef oAFMt0
#undef oAFMt1

// columns definition for "air handler" (AH) report/export
#define oAhr(m) offsetof( AHRES_IVL_SUB, m)
Expand Down Expand Up @@ -1258,10 +1269,10 @@ o && dvrip->rpDayEnd >= Top.tp_endDay ) <--- new year's bug! 2-94
vpRxRow( dvrip, &rxt, pIvl, shortIvlTexts[rxt.fq]); // do DHWMTR rpt row. Uses rxt.flags, colDef.
}

else if (dvrip->rpTy == C_RPTYCH_AFMTR) // if DHW meter report
else if (dvrip->rpTy == C_RPTYCH_AFMTR) // if AFMETER report
{
TI afMtri = dvrip->dv_afMtri; // subscript
AFMTR_IVL* pIvl = &AfMtrR[afMtri].Y + (rxt.fq - 1); // .M is after .Y, etc
TI afMtri = dvrip->dv_afMtri > 0 ? dvrip->dv_afMtri : AfMtrR.n; // subscript
AFMTR_IVL* pIvl = AfMtrR[afMtri].amt_GetAFMTR_IVL( rxt.fq);
rxt.colDef = afMtrColdef; // columns definition table for vpRxRow
vpRxRow(dvrip, &rxt, pIvl, shortIvlTexts[rxt.fq]); // do DHWMTR rpt row. Uses rxt.flags, colDef.
}
Expand Down Expand Up @@ -1487,8 +1498,10 @@ void DVRI::dv_vpAfMtrRow(RXPORTINFO *rxt, TI afMtri /*=-1*/)
{
if (afMtri < 0)
afMtri = dv_afMtri;
if (afMtri == TI_SUM)
afMtri = AfMtrR.n; // handle "sum"
AFMTR* pM = AfMtrR.GetAt(afMtri); // record
AFMTR_IVL* pIvl = (&pM->Y) + (rxt->fq - 1); // interval
AFMTR_IVL* pIvl = pM->amt_GetAFMTR_IVL( rxt->fq); // interval

vpRxRow(this, rxt, pIvl, rxt->col1, pM->name, &rxt->xebM, &rxt->xebD, &rxt->xebH, rxt->xebS);
} // dv_vpDHWMtrRow
Expand Down
16 changes: 10 additions & 6 deletions src/CNCULT4.CPP
Original file line number Diff line number Diff line change
Expand Up @@ -695,8 +695,7 @@ badZn4ty:
// check meter reference or ALL or SUM

if (mtri > 0) // if specific meter given (error'd above if omitted when rqd)
{
if (ckRefPt( &MtrB, mtri, isEx ? "exMeter" : "rpMeter" ) )
{ if (ckRefPt( &MtrB, mtri, isEx ? "exMeter" : "rpMeter" ) )
return RCBAD;
}
else // no meter given, or ALL or SUM.
Expand Down Expand Up @@ -769,10 +768,15 @@ badDHWMtr4ty:
{
char *mtrTx /*=""*/;
if (ri_afMtri == TI_SUM)
{
mtrTx = "sum";
goto badAFMtr4ty;
}
switch (rpTy)
{
case 0: // rpTy 0: not set, no message here
case C_RPTYCH_AFMTR:
break; // AFMTR (air flow meter): SUM allowed.
default:
mtrTx = "sum";
goto badAFMtr4ty;
}
else if (ri_afMtri == TI_ALL)
switch (rpTy)
{
Expand Down
20 changes: 13 additions & 7 deletions src/CNGUTS.CPP
Original file line number Diff line number Diff line change
Expand Up @@ -547,12 +547,13 @@ LOCAL RC FC NEAR doBegIvl() // simulation run start-of-interval processing: init
EF( Top.tp_ExshBegHour()); // Penumbra external shading: sets sun position

default: // case C_IVLCH_S: // at start of each subhour, incl longer intervals (fall in)
Top.isEndHour = (Top.iSubhr + 1 >= Top.nSubSteps); // set flag if last subHour of hour

#if defined( DEBUGDUMP)
DbDo( dbdSTARTSTEP); // nothing yet debug-printed for this subhour
// (sets flag re on-demand heading printing
#endif
EF( Top.tp_WthrBegSubhr() ); // set Top subhourly weather members, eg tDbOSh. Mostly interpolated. cgwthr.cpp.
Top.isEndHour = (Top.iSubhr + 1 >= Top.nSubSteps); // set flag if last subHour of hour

// clear subhour values in air flow meters
AFMTR* pAM;
Expand Down Expand Up @@ -1563,9 +1564,12 @@ LOCAL void FC NEAR doIvlAccum()
AFMTR* pAMSum = AfMtrR.p + AfMtrR.n;
AFMTR* pAM;
RLUP(AfMtrR, pAM) // loop AFMTRs
{ if (pAM->ss < AfMtrR.n)
pAMSum->S.amt_Accum(&pAM->S, pAM->ss == 1, pAM->ss == AfMtrR.n - 1);
pAM->amt_Accum( C_IVLCH_H, Top.isBegHour, Top.isEndHour);
{
if (pAM->ss < AfMtrR.n)
{ pAMSum->S[0].amt_Accum(pAM->S, pAM->ss == 1, pAM->ss == AfMtrR.n - 1);
pAMSum->S[1].amt_Accum(pAM->S+1, pAM->ss == 1, pAM->ss == AfMtrR.n - 1);
pAM->amt_Accum(C_IVLCH_H, Top.isBegHour, Top.isEndHour);
}
}

if (Top.ivl > C_IVLCH_H) // if subhour call, done
Expand Down Expand Up @@ -1724,8 +1728,8 @@ LOCAL void FC NEAR doIvlAccum()
RLUP(WsResR, pWSR) // loop DHWSYS simulation results incl sum_of.
pWSR->M.wsr_Accum(&pWSR->D, Top.isBegMonth, Top.isEndMonth); // accumulate month from day
RLUP( AhresB, ahres) // loop air handers sim results
accumAhr( &ahres->D, &ahres->M, Top.isBegMonth, Top.isEndMonth); // accumulate day ah results to month
mtrsAccum( C_IVLCH_M, Top.isBegMonth, Top.isEndMonth); // accum metered energy: day to month. local,below.
accumAhr( &ahres->D, &ahres->M, Top.isBegMonth, Top.isEndMonth); // accumulate day ah results to month
mtrsAccum( C_IVLCH_M, Top.isBegMonth, Top.isEndMonth); // accum METERs, DHWMETERs, AFMETERS: day to month
#ifdef BINRES
if (brf) // if outputting binary results for this run
//if (!Top.tp_autoSizing) // not for ausz yet 6-95: tested above, and brf is off.
Expand Down Expand Up @@ -2054,7 +2058,9 @@ LOCAL void FC NEAR mtrsAccum( // Accumulate metered results: add interval to ne
// AFMETERs
AFMTR* pAM;
RLUP(AfMtrR, pAM)
pAM->amt_Accum(ivl, firstflg, lastflg);
{ if (pAM->ss < AfMtrR.n)
pAM->amt_Accum(ivl, firstflg, lastflg);
}
} // mtrsAccum
//-----------------------------------------------------------------------------------------------------------
LOCAL void FC NEAR mtrsFinalize( // Finalize meters (after post-stage calcs e.g. battery)
Expand Down
Loading