Skip to content

Commit dc8f71c

Browse files
authored
Merge pull request #107 from cse-sim/reportinfil
AFMETER now tracks both positive and negative air flows by AFCAT. REPORT rpType=AFMTR displays both pos and neg values.
2 parents 53f4063 + 244582e commit dc8f71c

File tree

7 files changed

+157
-97
lines changed

7 files changed

+157
-97
lines changed

src/CGCOMP.CPP

Lines changed: 82 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -265,27 +265,40 @@ float TOPRAT::tp_WindPresV( // wind velocity pressure
265265
// NAFCATS s/b same as AFCAT choices + 1 (for total)
266266
static_assert(AFMTR_IVL::NAFCATS == C_AFCAT_COUNT+1, "Inconsistent AFMTR constants");
267267
//-----------------------------------------------------------------------------
268-
void AFMTR_IVL::amt_Copy(
269-
const AFMTR_IVL* s)
268+
void AFMTR_IVL::amt_Copy( // copy
269+
const AFMTR_IVL* sIvl, // source
270+
float mult /*=1.f*/) // optional multiplier
270271
{
271-
memcpy(this, s, sizeof(AFMTR_IVL));
272+
if (mult == 1.f)
273+
memcpy(this, sIvl, sizeof(AFMTR_IVL));
274+
else
275+
{ amt_count = sIvl->amt_count;
276+
VCopy(&amt_total, NAFCATS, &sIvl->amt_total, double(mult));
277+
}
272278
} // AFMTR_IVL::amt_Copy
273279
//-----------------------------------------------------------------------------
274280
void AFMTR_IVL::amt_Accum( // accumulate
275281
const AFMTR_IVL* sIvl, // source
276282
int firstFlg, // true iff first accum into this (beg of ivl)
277-
int lastFlg) // true iff last accum into this (end of ivl)
278-
283+
int lastFlg, // true iff last accum into this (end of ivl)
284+
int options /*=0*/) // option bits
285+
// 1: use sIvl.amt_count to scale totals
286+
// effectively averages by day for annual values
287+
// 2: sum only (do not average)
279288
{
289+
int count = (options & 1) ? sIvl->amt_count : 1;
280290
if (firstFlg)
281-
{ amt_Copy(sIvl);
282-
amt_count = 1;
291+
{ amt_Copy(sIvl, float( count));
292+
amt_count = count;
283293
}
284294
else
285-
{ VAccum(&amt_total, NAFCATS, &sIvl->amt_total);
286-
amt_count++;
295+
{ VAccum(&amt_total, NAFCATS, &sIvl->amt_total, float( count));
296+
amt_count += count;
287297
}
288-
if (lastFlg)
298+
299+
// average unless caller says don't
300+
// Note: VMul1() nops if amt_count==1
301+
if (lastFlg && !(options & 2))
289302
VMul1(&amt_total, NAFCATS, 1.f / amt_count);
290303
} // AFMTR_IVL
291304
//-----------------------------------------------------------------------------
@@ -296,33 +309,51 @@ RC AFMTR::amt_CkF()
296309
//-----------------------------------------------------------------------------
297310
RC AFMTR::amt_BegSubhr() // init at beg of subhr
298311
{
299-
S.amt_Clear();
312+
S[ 0].amt_Clear();
313+
S[ 1].amt_Clear();
300314
return RCOK;
301315
} // AFMTR::amt_BegSubhr
302316
//-----------------------------------------------------------------------------
303317
void AFMTR::amt_AccumCat( // accumulate air flow value for current subhour
304318
AFCAT afCat, // air flow category
305319
float amf) // air mass flow, lbm/sec
306320
{
307-
if (amf > 0.f) // record only flow into zone
308-
{ // convert lbm/s -> cfm std air
309-
S.amt_AccumCat(afCat, AMFtoAVF2( amf));
310-
}
321+
int iNeg = amf < 0.f;
322+
S[ iNeg].amt_AccumCat(afCat, AMFtoAVF2(amf));
311323
} // AFMTR::amt_AccumCat
312324
//-----------------------------------------------------------------------------
325+
AFMTR_IVL* AFMTR::amt_GetAFMTR_IVL(
326+
IVLCH ivl, // interval
327+
int iPN /*=0*/) // flow direction 0: pos (in), 1: neg (out)
328+
{
329+
return Y + 2 * (ivl - C_IVLCH_Y) + iPN;
330+
}
331+
//-----------------------------------------------------------------------------
313332
void AFMTR::amt_Accum(
314333
IVLCH ivl, // destination interval: hour/day/month/year
315334
// Accumulates from subhour/day/month. Not Top.ivl!
316335
int firstFlg, // iff TRUE, destination will be initialized before values are accumulated into it
317336
int lastFlg) // iff TRUE, destination averages will be computed as needed
318337
{
319-
AFMTR_IVL* dIvl = &Y + (ivl - C_IVLCH_Y); // point destination substruct for interval
320-
// ASSUMES interval members ordered like DTIVLCH choices
321-
AFMTR_IVL* sIvl = dIvl + 1; // source: next shorter interval
338+
AFMTR_IVL* dIvl0 = amt_GetAFMTR_IVL( ivl); // point destination substruct for interval
339+
// ASSUMES interval members ordered like DTIVLCH choices
340+
AFMTR_IVL* sIvl0 = amt_GetAFMTR_IVL(ivl + 1); // source: next shorter interval
341+
342+
int options = 0; // default: track average
322343

323-
// accumulate: copy on first call (in lieu of 0'ing dIvl).
324-
// Note: amt_Init() call in doBegIvl 0s H values
325-
dIvl->amt_Accum(sIvl, firstFlg, lastFlg);
344+
if (ivl == C_IVLCH_Y)
345+
options = 1; // average by day for non-sum-of year values
346+
// handles diffs due to month length
347+
for (int iPN=0; iPN<2; iPN++)
348+
dIvl0[ iPN].amt_Accum(sIvl0+iPN, firstFlg, lastFlg, options);
349+
350+
if (lastFlg)
351+
{
352+
AFMTR* pAMSum = AfMtrR.p + AfMtrR.n;
353+
AFMTR_IVL* dIvlSum0 = pAMSum->amt_GetAFMTR_IVL( ivl);
354+
for (int iPN = 0; iPN < 2; iPN++)
355+
dIvlSum0[ iPN].amt_Accum(dIvl0+iPN, ss == 1, 0);
356+
}
326357
} // AFMTR::amt_Accum
327358
//=============================================================================
328359

@@ -518,23 +549,13 @@ double ZNR::zn_Rho0() const // zone air density
518549
// returns moist air density lb/ft3 at nominal z=0 for current zone conditions
519550
// Note: not *dry* air
520551
{
521-
#if 1 // air density rework, 10-18-2012
522552
double rho = psyDenMoistAir( tz, wz, LbSfToInHg( zn_pz0));
523553
if (rho < .0001)
524554
{ err( WRN, "Zone '%s', %s: moist air density <= 0\n",
525555
name, Top.When( C_IVLCH_S));
526556
rho = 0.01; // set to small but physically possible value
527557
}
528558
return rho;
529-
#elif 1
530-
x double rho1 = psyDenMoistAir( tz, wz, LbSfToInHg( zn_pz0));
531-
x double rho2 = psyDensity( tz, wz, LbSfToInHg( zn_pz0));
532-
x if (FEQX( rho1, rho2) > .001)
533-
x printf( "Mismatch\n");
534-
x return rho2;
535-
#else
536-
x return psyDensity( tz, wz, LbSfToInHg( zn_pz0));
537-
#endif
538559
} // ZNR::zn_Rho0
539560
//------------------------------------------------------------------------------
540561
void ZNR::zn_AccumAirFlow( // accumulate zone bal values due to air flow
@@ -1034,15 +1055,28 @@ void IZXRAT::iz_SetupAfMtrs()
10341055

10351056
// AFMTR ptrs: NULL if no meter specified -> no air flow accounting
10361057
// one pointer for positive flows, one for negative
1037-
const ZNR* zp;
1038-
if (iz_zi1 > 0)
1039-
{ zp = ZrB.GetAt(iz_zi1);
1040-
iz_pPosAfMtr = AfMtrR.GetAtSafe(zp->i.zn_afMtri);
1041-
}
1042-
if (iz_zi2 > 0)
1043-
{ zp = ZrB.GetAt(iz_zi2);
1044-
iz_pNegAfMtr = AfMtrR.GetAtSafe(zp->i.zn_afMtri);
1058+
iz_pAfMtr1 = iz_pAfMtr2 = NULL; // insurance
1059+
if (iz_afCat > 0)
1060+
{ // set up ptrs to AFMTR(s)
1061+
const ZNR* zp;
1062+
if (iz_zi1 > 0)
1063+
{ zp = ZrB.GetAt(iz_zi1);
1064+
iz_pAfMtr1 = AfMtrR.GetAtSafe(zp->i.zn_afMtri);
1065+
}
1066+
if (iz_zi2 > 0)
1067+
{ // interzone transfers recorded iff to a different meter
1068+
zp = ZrB.GetAt(iz_zi2);
1069+
AFMTR* pAM = AfMtrR.GetAtSafe(zp->i.zn_afMtri);
1070+
if (pAM == iz_pAfMtr1)
1071+
iz_pAfMtr1 = NULL; // same meter on both sides of IZ
1072+
// don't record IZ within meter
1073+
else
1074+
iz_pAfMtr2 = pAM; // z2 meter specified and differs from z1
1075+
}
10451076
}
1077+
iz_doingAfMtr // say this IZXRAT has AFMTR (speedier test)
1078+
= iz_pAfMtr1 != NULL || iz_pAfMtr2 != NULL;
1079+
10461080
} // IZXRAT::iz_SetupAfMtrs
10471081
//-----------------------------------------------------------------------------
10481082
AFCAT IZXRAT::iz_AfCatDefault() const
@@ -1061,8 +1095,10 @@ AFCAT IZXRAT::iz_AfCatDefault() const
10611095
else
10621096
{ if (iz_IsFixedFlow())
10631097
afCat = C_AFCAT_FANIZ;
1064-
else
1098+
else if (iz_IsAirNet())
10651099
afCat = C_AFCAT_INFILIZ;
1100+
else
1101+
afCat = 0;
10661102
}
10671103

10681104
return afCat;
@@ -1505,14 +1541,12 @@ RC IZXRAT::iz_EndSubhr() // end-of-subhour vent calcs
15051541
if (iz_nvcntrl == C_IZNVTYCH_ANHORIZ)
15061542
iz_amfNom
15071543
+= (1.f - fVent)*iz_ad[0].ad_mdotB + fVent * iz_ad[1].ad_mdotB;
1508-
if (iz_amfNom > 0.f)
1509-
{ if (iz_pPosAfMtr)
1510-
iz_pPosAfMtr->amt_AccumCat(iz_afCat, iz_amfNom);
1511-
}
1512-
else if (iz_amfNom < 0.f)
1513-
{ // flow is out of zn1 = into zn2
1514-
if (iz_pNegAfMtr)
1515-
iz_pNegAfMtr->amt_AccumCat(iz_afCat, -iz_amfNom);
1544+
if (iz_doingAfMtr && iz_amfNom != 0.f)
1545+
{ if (iz_pAfMtr1)
1546+
iz_pAfMtr1->amt_AccumCat(iz_afCat, iz_amfNom);
1547+
if (iz_pAfMtr2)
1548+
// flow is opposite direction from z2 POV
1549+
iz_pAfMtr2->amt_AccumCat(iz_afCat, -iz_amfNom);
15161550
}
15171551

15181552
return RCOK;

src/CGRESULT.CPP

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,9 @@ static COLDEF wMtrColdef[] =
235235
#undef oWMtr
236236

237237
// columns definition for "Airflow meter" (AFMTR) report/export
238-
#define oAFMtr(m) offsetof( AFMTR_IVL, m)
239-
#define D 3 // decimal digits
238+
#define oAFMt0(m) offsetof( AFMTR_IVL, m)
239+
#define oAFMt1(m) (offsetof( AFMTR_IVL, m)+sizeof( AFMTR_IVL))
240+
#define D 1 // decimal digits
240241
static COLDEF afMtrColdef[] =
241242
/* max offset cvflag */
242243
/* colhd flags wid dfw (cnguts.h) (above) */
@@ -247,21 +248,31 @@ static COLDEF afMtrColdef[] =
247248
{ "Day", 8 | 4, 2, 0, USE_NEXT_ARG, CVI },
248249
{ "Hr", 8 | 4, 2, 0, USE_NEXT_ARG, CVI },
249250
{ "Subhr", 8 | 4, 1, 0, USE_NEXT_ARG, CVS }, // ..
250-
{ "Total", 0, 7, D, oAFMtr(amt_total), CV1 },
251-
{ "Unknown", 0, 7, D, oAFMtr(amt_unknown),CV1 },
252-
{ "InfilEx", 0, 7, D, oAFMtr(amt_infilEx),CV1 },
253-
{ "VentEx", 0, 7, D, oAFMtr(amt_ventEx), CV1 },
254-
{ "FanEx", 0, 7, D, oAFMtr(amt_fanEx), CV1 },
255-
{ "InfilIz", 0, 7, D, oAFMtr(amt_infilIz),CV1 },
256-
{ "VentIz", 0, 7, D, oAFMtr(amt_ventIz), CV1 },
257-
{ "FanIz", 0, 7, D, oAFMtr(amt_fanIz), CV1 },
258-
{ "DuctLk", 0, 7, D, oAFMtr(amt_ductLk), CV1 },
259-
{ "HVAC", 0, 7, D, oAFMtr(amt_hvac), CV1 },
251+
{ "Tot+", 0, 5, D, oAFMt0(amt_total), CV1 },
252+
{ "Unkn+", 0, 5, D, oAFMt0(amt_unknown),CV1 },
253+
{ "InfX+", 0, 5, D, oAFMt0(amt_infilEx),CV1 },
254+
{ "VntX+", 0, 5, D, oAFMt0(amt_ventEx), CV1 },
255+
{ "FanX+", 0, 5, D, oAFMt0(amt_fanEx), CV1 },
256+
{ "InfZ+", 0, 5, D, oAFMt0(amt_infilIz),CV1 },
257+
{ "VntZ+", 0, 5, D, oAFMt0(amt_ventIz), CV1 },
258+
{ "FanZ+", 0, 5, D, oAFMt0(amt_fanIz), CV1 },
259+
{ "Duct+", 0, 5, D, oAFMt0(amt_ductLk), CV1 },
260+
{ "HVAC+", 0, 5, D, oAFMt0(amt_hvac), CV1 },
261+
{ "Tot-", 0, 5, D, oAFMt1(amt_total), CV1 },
262+
{ "Unkn-", 0, 5, D, oAFMt1(amt_unknown),CV1 },
263+
{ "InfX-", 0, 5, D, oAFMt1(amt_infilEx),CV1 },
264+
{ "VntX-", 0, 5, D, oAFMt1(amt_ventEx), CV1 },
265+
{ "FanX-", 0, 5, D, oAFMt1(amt_fanEx), CV1 },
266+
{ "InfZ-", 0, 5, D, oAFMt1(amt_infilIz),CV1 },
267+
{ "VntZ-", 0, 5, D, oAFMt1(amt_ventIz), CV1 },
268+
{ "FanZ-", 0, 5, D, oAFMt1(amt_fanIz), CV1 },
269+
{ "Duct-", 0, 5, D, oAFMt1(amt_ductLk), CV1 },
270+
{ "HVAC-", 0, 5, D, oAFMt1(amt_hvac), CV1 },
260271
{ 0, 0, 0, 0, 0, CV1 }
261272
};
262273
#undef D
263-
#undef oAFMtr
264-
274+
#undef oAFMt0
275+
#undef oAFMt1
265276

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

1261-
else if (dvrip->rpTy == C_RPTYCH_AFMTR) // if DHW meter report
1272+
else if (dvrip->rpTy == C_RPTYCH_AFMTR) // if AFMETER report
12621273
{
1263-
TI afMtri = dvrip->dv_afMtri; // subscript
1264-
AFMTR_IVL* pIvl = &AfMtrR[afMtri].Y + (rxt.fq - 1); // .M is after .Y, etc
1274+
TI afMtri = dvrip->dv_afMtri > 0 ? dvrip->dv_afMtri : AfMtrR.n; // subscript
1275+
AFMTR_IVL* pIvl = AfMtrR[afMtri].amt_GetAFMTR_IVL( rxt.fq);
12651276
rxt.colDef = afMtrColdef; // columns definition table for vpRxRow
12661277
vpRxRow(dvrip, &rxt, pIvl, shortIvlTexts[rxt.fq]); // do DHWMTR rpt row. Uses rxt.flags, colDef.
12671278
}
@@ -1487,8 +1498,10 @@ void DVRI::dv_vpAfMtrRow(RXPORTINFO *rxt, TI afMtri /*=-1*/)
14871498
{
14881499
if (afMtri < 0)
14891500
afMtri = dv_afMtri;
1501+
if (afMtri == TI_SUM)
1502+
afMtri = AfMtrR.n; // handle "sum"
14901503
AFMTR* pM = AfMtrR.GetAt(afMtri); // record
1491-
AFMTR_IVL* pIvl = (&pM->Y) + (rxt->fq - 1); // interval
1504+
AFMTR_IVL* pIvl = pM->amt_GetAFMTR_IVL( rxt->fq); // interval
14921505
14931506
vpRxRow(this, rxt, pIvl, rxt->col1, pM->name, &rxt->xebM, &rxt->xebD, &rxt->xebH, rxt->xebS);
14941507
} // dv_vpDHWMtrRow

src/CNCULT4.CPP

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -695,8 +695,7 @@ badZn4ty:
695695
// check meter reference or ALL or SUM
696696

697697
if (mtri > 0) // if specific meter given (error'd above if omitted when rqd)
698-
{
699-
if (ckRefPt( &MtrB, mtri, isEx ? "exMeter" : "rpMeter" ) )
698+
{ if (ckRefPt( &MtrB, mtri, isEx ? "exMeter" : "rpMeter" ) )
700699
return RCBAD;
701700
}
702701
else // no meter given, or ALL or SUM.
@@ -769,10 +768,15 @@ badDHWMtr4ty:
769768
{
770769
char *mtrTx /*=""*/;
771770
if (ri_afMtri == TI_SUM)
772-
{
773-
mtrTx = "sum";
774-
goto badAFMtr4ty;
775-
}
771+
switch (rpTy)
772+
{
773+
case 0: // rpTy 0: not set, no message here
774+
case C_RPTYCH_AFMTR:
775+
break; // AFMTR (air flow meter): SUM allowed.
776+
default:
777+
mtrTx = "sum";
778+
goto badAFMtr4ty;
779+
}
776780
else if (ri_afMtri == TI_ALL)
777781
switch (rpTy)
778782
{

src/CNGUTS.CPP

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -547,12 +547,13 @@ LOCAL RC FC NEAR doBegIvl() // simulation run start-of-interval processing: init
547547
EF( Top.tp_ExshBegHour()); // Penumbra external shading: sets sun position
548548

549549
default: // case C_IVLCH_S: // at start of each subhour, incl longer intervals (fall in)
550+
Top.isEndHour = (Top.iSubhr + 1 >= Top.nSubSteps); // set flag if last subHour of hour
551+
550552
#if defined( DEBUGDUMP)
551553
DbDo( dbdSTARTSTEP); // nothing yet debug-printed for this subhour
552554
// (sets flag re on-demand heading printing
553555
#endif
554556
EF( Top.tp_WthrBegSubhr() ); // set Top subhourly weather members, eg tDbOSh. Mostly interpolated. cgwthr.cpp.
555-
Top.isEndHour = (Top.iSubhr + 1 >= Top.nSubSteps); // set flag if last subHour of hour
556557

557558
// clear subhour values in air flow meters
558559
AFMTR* pAM;
@@ -1563,9 +1564,12 @@ LOCAL void FC NEAR doIvlAccum()
15631564
AFMTR* pAMSum = AfMtrR.p + AfMtrR.n;
15641565
AFMTR* pAM;
15651566
RLUP(AfMtrR, pAM) // loop AFMTRs
1566-
{ if (pAM->ss < AfMtrR.n)
1567-
pAMSum->S.amt_Accum(&pAM->S, pAM->ss == 1, pAM->ss == AfMtrR.n - 1);
1568-
pAM->amt_Accum( C_IVLCH_H, Top.isBegHour, Top.isEndHour);
1567+
{
1568+
if (pAM->ss < AfMtrR.n)
1569+
{ pAMSum->S[0].amt_Accum(pAM->S, pAM->ss == 1, pAM->ss == AfMtrR.n - 1);
1570+
pAMSum->S[1].amt_Accum(pAM->S+1, pAM->ss == 1, pAM->ss == AfMtrR.n - 1);
1571+
pAM->amt_Accum(C_IVLCH_H, Top.isBegHour, Top.isEndHour);
1572+
}
15691573
}
15701574

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

0 commit comments

Comments
 (0)