@@ -257,6 +257,76 @@ float TOPRAT::tp_WindPresV( // wind velocity pressure
257257} // TOPRAT::tp_WindPresV
258258// ===============================================================================
259259
260+ // /////////////////////////////////////////////////////////////////////////////
261+ // AFMTR_IVL, AFMTR: accumulates air mass flow by category
262+ // /////////////////////////////////////////////////////////////////////////////
263+ /* static*/ const int AFMTR_IVL::NAFCATS
264+ = (sizeof (AFMTR_IVL) - offsetof( AFMTR_IVL, amt_total)) / sizeof (float );
265+ // NAFCATS s/b same as AFCAT choices + 1 (for total)
266+ static_assert (AFMTR_IVL::NAFCATS == C_AFCAT_COUNT+1 , " Inconsistent AFMTR constants" );
267+ // -----------------------------------------------------------------------------
268+ void AFMTR_IVL::amt_Copy (
269+ const AFMTR_IVL* s)
270+ {
271+ memcpy (this , s, sizeof (AFMTR_IVL));
272+ } // AFMTR_IVL::amt_Copy
273+ // -----------------------------------------------------------------------------
274+ void AFMTR_IVL::amt_Accum ( // accumulate
275+ const AFMTR_IVL* sIvl , // source
276+ int firstFlg, // true iff first accum into this (beg of ivl)
277+ int lastFlg) // true iff last accum into this (end of ivl)
278+
279+ {
280+ if (firstFlg)
281+ { amt_Copy (sIvl );
282+ amt_count = 1 ;
283+ }
284+ else
285+ { VAccum (&amt_total, NAFCATS, &sIvl ->amt_total );
286+ amt_count++;
287+ }
288+ if (lastFlg)
289+ VMul1 (&amt_total, NAFCATS, 1 .f / amt_count);
290+ } // AFMTR_IVL
291+ // -----------------------------------------------------------------------------
292+ RC AFMTR::amt_CkF ()
293+ {
294+ return RCOK;
295+ }
296+ // -----------------------------------------------------------------------------
297+ RC AFMTR::amt_BegSubhr () // init at beg of subhr
298+ {
299+ S.amt_Clear ();
300+ return RCOK;
301+ } // AFMTR::amt_BegSubhr
302+ // -----------------------------------------------------------------------------
303+ void AFMTR::amt_AccumCat ( // accumulate air flow value for current subhour
304+ AFCAT afCat, // air flow category
305+ float amf) // air mass flow, lbm/sec
306+ {
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+ }
311+ } // AFMTR::amt_AccumCat
312+ // -----------------------------------------------------------------------------
313+ void AFMTR::amt_Accum (
314+ IVLCH ivl, // destination interval: hour/day/month/year
315+ // Accumulates from subhour/day/month. Not Top.ivl!
316+ int firstFlg, // iff TRUE, destination will be initialized before values are accumulated into it
317+ int lastFlg) // iff TRUE, destination averages will be computed as needed
318+ {
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
322+
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);
326+ } // AFMTR::amt_Accum
327+ // =============================================================================
328+
329+
260330// ///////////////////////////////////////////////////////////////////////////////
261331// AIRSTATE
262332// ///////////////////////////////////////////////////////////////////////////////
@@ -704,8 +774,7 @@ RC IZXRAT::iz_SetupHERV() // set mbrs re HERV model
704774 DbPrintf ( " HERV '%s' in: avf=%.2f rho=%.5f mdotP=%.5f\n out: avf=%.2f rho=%.5f mdotP=%.5f\n " ,
705775 name, avfGross, iz_rho2, ad.ad_mdotP , avfGross*iz_vfExhRat, rhoX, ad.ad_mdotX );
706776#endif
707-
708-
777+
709778 // iz_air2 / iz_rho2 = air state into z1
710779 // Note: calc HX with moist air mass flow rates
711780 // some sources say dry AMF, not fully understood
@@ -951,9 +1020,54 @@ x }
9511020
9521021 iz_SetupNonAirNet (); // calc izxfer derived values
9531022
1023+ iz_SetupAfMtrs (); // AFMETER (air flow meter) setup
1024+
9541025 return rc;
955- } // IZXRAT::iz_Setup()
1026+ } // IZXRAT::iz_Setup
9561027#undef ZFAN
1028+ // -------------------------------------------------------------------
1029+ void IZXRAT::iz_SetupAfMtrs ()
1030+ {
1031+ // Air flow category
1032+ if (iz_afCat == 0 )
1033+ iz_afCat = iz_AfCatDefault ();
1034+
1035+ // AFMTR ptrs: NULL if no meter specified -> no air flow accounting
1036+ // 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 );
1045+ }
1046+ } // IZXRAT::iz_SetupAfMtrs
1047+ // -----------------------------------------------------------------------------
1048+ AFCAT IZXRAT::iz_AfCatDefault () const
1049+ {
1050+ AFCAT afCat;
1051+ if (iz_IsSysAir ())
1052+ afCat = C_AFCAT_HVAC;
1053+ else if (iz_IsDuctLk ())
1054+ afCat = C_AFCAT_DUCTLK;
1055+ else if (iz_IsExterior ())
1056+ { if (iz_IsFixedFlow ())
1057+ afCat = C_AFCAT_FANEX;
1058+ else
1059+ afCat = C_AFCAT_INFILEX;
1060+ }
1061+ else
1062+ { if (iz_IsFixedFlow ())
1063+ afCat = C_AFCAT_FANIZ;
1064+ else
1065+ afCat = C_AFCAT_INFILIZ;
1066+ }
1067+
1068+ return afCat;
1069+
1070+ } // IZXRAT::iz_AfcatDefault
9571071// -----------------------------------------------------------------------------
9581072RC IZXRAT::iz_SetupNonAirNet () // interzone transfer one-time initialization
9591073
@@ -1096,6 +1210,8 @@ TI ZNR::zn_AddIZXFER( // add IZXFER coupled to this zone
10961210 else
10971211 ize->iz_zi2 = -1 ; // no other zone
10981212
1213+ ize->iz_SetupAfMtrs (); // default iz_afCat, set up AFMTR linkage
1214+
10991215 // more init?
11001216
11011217 return ize->ss ;
@@ -1255,7 +1371,6 @@ RC IZXRAT::iz_Calc()
12551371 ZNR* zp1 = ZrB.GetAt ( iz_zi1);
12561372 ZNR* zp2 = ZrB.GetAt ( iz_zi2);
12571373 float tdif = zp1->tzls - zp2->tzls ; // temp diff between zones
1258- #if 1
12591374 if (iz_nvcntrl != C_IZNVTYCH_ONEWAY || tdif > 0 .f )
12601375 { double hx = iz_ua;
12611376 if (iz_nvcntrl != C_IZNVTYCH_NONE)
@@ -1264,15 +1379,6 @@ RC IZXRAT::iz_Calc()
12641379 zp1->zn_qIzXAnSh -= qx; // accumulate heat/hour to zone
12651380 zp2->zn_qIzXAnSh += qx; // same for other zone, opposite sign: positive into zone.
12661381 }
1267- #else
1268- x float hx = iz_ua; // coupling coeff: init to constant (conduction) portion
1269- x if (iz_nvcntrl==C_IZNVTYCH_TWOWAY) // if nat vent tween zones
1270- x hx += iz_nvcoeff * sqrt( fabs( tdif)); // it is proportional to sqrt temp difference
1271- x float qx = hx * tdif; // heat xfer per hour (power): coupling * temp diff.
1272- x // positive for xfer from zn1 to zn2
1273- x zp1->zn_qIzXAnSh -= qx; // accumulate heat/hour to zone
1274- x zp2->zn_qIzXAnSh += qx; // same for other zone, opposite sign: positive into zone.
1275- #endif
12761382 return RCOK;
12771383} // IZXRAT::iz_Calc
12781384// --------------------------------------------------------------------------------
@@ -1380,7 +1486,6 @@ RC IZXRAT::iz_EndSubhr() // end-of-subhour vent calcs
13801486{
13811487 ZNR* zp = ZrB.GetAt ( iz_zi1); // zone
13821488 float fVent = zp->zn_fVent ;
1383- iz_amfNom = (1 .f -fVent )*iz_ad[ 0 ].ad_mdotP + fVent *iz_ad[ 1 ].ad_mdotP ;
13841489 if (iz_HasFan () && iz_fan.fn_mtri )
13851490 { // calc fan electricity and accum to meter
13861491 // need venting fraction to determine fan operation
@@ -1393,18 +1498,34 @@ RC IZXRAT::iz_EndSubhr() // end-of-subhour vent calcs
13931498 iz_fan.fn_endUse , // user-specified end use (default = "fan")
13941499 fanPwr * Top.subhrDur ); // electrical energy, Btu (*not* Wh)
13951500 }
1501+
1502+ // air flow accounting
1503+ iz_amfNom // nominal flow, lbm/sec
1504+ = (1 .f - fVent )*iz_ad[0 ].ad_mdotP + fVent * iz_ad[1 ].ad_mdotP ;
1505+ if (iz_nvcntrl == C_IZNVTYCH_ANHORIZ)
1506+ iz_amfNom
1507+ += (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);
1516+ }
1517+
13961518 return RCOK;
13971519} // IZXRAT::iz_EndSubhr
1398-
13991520// =============================================================================
14001521
14011522// /////////////////////////////////////////////////////////////////////////////
14021523// struct AIRNET
14031524// finds zone pressures that achieve balanced mass flows
14041525// /////////////////////////////////////////////////////////////////////////////
14051526AIRNET::AIRNET ()
1406- : an_jac( NULL ), an_V1( NULL ), an_V2( NULL ), an_mdotAbs( NULL ), an_didLast( NULL ),
1407- an_nz(0 )
1527+ : an_jac( NULL ), an_V1( NULL ), an_V2( NULL ), an_mdotAbs( NULL ), an_didLast( NULL ),
1528+ an_nz(0 )
14081529{ an_resultsClear[0 ] = an_resultsClear[1 ] = 0 ;
14091530} // AIRNET::AIRNET
14101531// -----------------------------------------------------------------------------
0 commit comments