diff --git a/doc/input-output-reference/src/overview/group-airflow.tex b/doc/input-output-reference/src/overview/group-airflow.tex index 4d6aea4e36c..db393414b97 100644 --- a/doc/input-output-reference/src/overview/group-airflow.tex +++ b/doc/input-output-reference/src/overview/group-airflow.tex @@ -1518,7 +1518,7 @@ \subsection{ZoneRefrigerationDoorMixing}\label{zonerefrigerationdoormixing} ZoneRefrigerationDoorMixing is ideally suited for two zones, at least one of which is refrigerated, that exchange an equal amount of dry air. As with \hyperref[zonemixing]{ZoneMixing}, this is a simplified interzone airflow in EnergyPlus. The ZoneRefrigerationDoorMixing approach shares some features of both \hyperref[zonemixing]{ZoneMixing} and \hyperref[zonecrossmixing]{ZoneCrossMixing}. Like \hyperref[zonecrossmixing]{ZoneCrossMixing}, ZoneRefrigerationDoorMixing has an energy effect on both the source and the receiving zone, thus maintaining both the air mass and energy balances in the two zones. Unlike the other two mixing objects, ZoneRefrigerationDoorMixing always calculates the air exchange rate based on the zone temperature and relative humidity. That is, the user does not specify the air flow rate. The user can moderate the flow through a door-opening schedule. -ZoneRefrigerationDoorMixing can only be entered once for any unique pair of zones. It doesn't matter which zone is listed first and the zones will automatically switch back and forth between source and receiving zones depending upon which zone is colder. +ZoneRefrigerationDoorMixing can only be entered once for any unique pair of zones. It doesn't matter which zone is listed first and the zones will automatically switch back and forth between source and receiving zones depending upon which zone is colder. If space heat balance is active and a space name is specified for Space or Zone Name 1 or 2, then the space conditions will be used and the exchange will be with that space only. If space heat balance is active and a zone name is specified, then the aveerage zone conditions will be used, and the exchange will be proportioned to all spaces in the zone by space volume. \subsubsection{Inputs}\label{inputs-7-003} @@ -1526,13 +1526,13 @@ \subsubsection{Inputs}\label{inputs-7-003} The name of the ZoneRefrigerationDoorMixing object. -\paragraph{Field: Zone 1~ Name}\label{field-zone-1-name} +\paragraph{Field: Zone or Space Name 1}\label{field-zone-1-name} -This field is the name of one of the two zones (ref: Zone) exchanging air and attaches a particular refrigeration door~ mixing statement to both thermal zones in the building. +This field is the name of one of the two zones (ref: Zone) or spaces exchanging air and attaches a particular refrigeration door~ mixing statement to both thermal zones or spaces in the building. If a space name is used, it must belong to a different zone than Zone or Space Name 2. -\paragraph{Field: Zone 2~ Name}\label{field-zone-2-name} +\paragraph{Field: Zone or Space Name 2}\label{field-zone-2-name} -This field is the name of the other zone (ref: Zone) exchanging air and attaches a particular refrigeration door~ mixing statement to both thermal zones in the building. +This field is the name of the other zone (ref: Zone) or space exchanging air and attaches a particular refrigeration door~ mixing statement to both thermal zones or spaces in the building. If a space name is used, it must belong to a different zone than Zone or Space Name 1. \paragraph{Field: Schedule Name}\label{field-schedule-name-5} diff --git a/idd/Energy+.idd.in b/idd/Energy+.idd.in index d0901eae735..a3ebbedd817 100644 --- a/idd/Energy+.idd.in +++ b/idd/Energy+.idd.in @@ -24572,7 +24572,7 @@ ZoneCrossMixing, ZoneRefrigerationDoorMixing, \min-fields 4 - \memo Refrigeration Door Mixing is used for an opening between two zones that are at the + \memo Refrigeration Door Mixing is used for an opening between two zones (or spaces) that are at the \memo same elevation but have different air temperatures. In this case, the mixing air flow \memo between the two zones is determined by the density difference between the two zones. \memo This would typically be used between two zones in a refrigerated warehouse that are @@ -24581,14 +24581,18 @@ ZoneRefrigerationDoorMixing, A1 , \field Name \required-field \type alpha - A2 , \field Zone 1 Name + A2 , \field Zone or Space Name 1 + \note If a space name is used, it must belong to a different zone than Zone or Space Name 2. \required-field \type object-list \object-list ZoneNames - A3 , \field Zone 2 Name + \object-list SpaceNames + A3 , \field Zone or Space Name 2 + \note If a space name is used, it must belong to a different zone than Zone or Space Name 1. \required-field \type object-list \object-list ZoneNames + \object-list SpaceNames A4 , \field Schedule Name \note This schedule defines the fraction of the time the refrigeration door is open \note For example, if the warehouse is closed at night and there are no door openings diff --git a/src/EnergyPlus/HeatBalanceAirManager.cc b/src/EnergyPlus/HeatBalanceAirManager.cc index e9745fcad4f..870f2f35162 100644 --- a/src/EnergyPlus/HeatBalanceAirManager.cc +++ b/src/EnergyPlus/HeatBalanceAirManager.cc @@ -3802,7 +3802,8 @@ void GetSimpleAirModelInputs(EnergyPlusData &state, bool &ErrorsFound) // IF err int AlphaNum = 2; int Zone1Num = Util::FindItemInList(cAlphaArgs(AlphaNum), state.dataHeatBal->Zone); - if (Zone1Num == 0) { + int space1Num = Util::FindItemInList(cAlphaArgs(AlphaNum), state.dataHeatBal->space); + if ((Zone1Num == 0) && (space1Num==0)) { ShowSevereError(state, format("{}{}=\"{}\", invalid (not found) {}=\"{}\".", RoutineName, @@ -3811,11 +3812,14 @@ void GetSimpleAirModelInputs(EnergyPlusData &state, bool &ErrorsFound) // IF err cAlphaFieldNames(AlphaNum), cAlphaArgs(AlphaNum))); ErrorsFound = true; + } else if (Zone1Num == 0) { + Zone1Num = state.dataHeatBal->space(space1Num).zoneNum; } ++AlphaNum; // 3 int Zone2Num = Util::FindItemInList(cAlphaArgs(AlphaNum), state.dataHeatBal->Zone); - if (Zone2Num == 0) { + int space2Num = Util::FindItemInList(cAlphaArgs(AlphaNum), state.dataHeatBal->space); + if ((Zone2Num == 0) && (space2Num==0)) { ShowSevereError(state, format("{}{}=\"{}\", invalid (not found) {}=\"{}\".", RoutineName, @@ -3824,7 +3828,12 @@ void GetSimpleAirModelInputs(EnergyPlusData &state, bool &ErrorsFound) // IF err cAlphaFieldNames(AlphaNum), cAlphaArgs(AlphaNum))); ErrorsFound = true; + } else if (Zone2Num == 0) { + Zone2Num = state.dataHeatBal->space(space2Num).zoneNum; } + + int spaceNumA = 0; + int spaceNumB = 0; if (Zone1Num == Zone2Num) { ShowSevereError(state, format("{}{}=\"{}\", The same zone name has been entered for both sides of a refrigerated door {}=\"{}\".", @@ -3837,9 +3846,13 @@ void GetSimpleAirModelInputs(EnergyPlusData &state, bool &ErrorsFound) // IF err } else if (Zone1Num < Zone2Num) { // zone 1 will come first in soln loop, id zone 2 as mate zone ZoneNumA = Zone1Num; ZoneNumB = Zone2Num; + spaceNumA = space1Num; + spaceNumB = space2Num; } else { // zone 2 will come first in soln loop, id zone 1 as mate zone ZoneNumA = Zone2Num; ZoneNumB = Zone1Num; + spaceNumA = space2Num; + spaceNumB = space1Num; } if (!allocated(state.dataHeatBal->RefDoorMixing(ZoneNumA).OpenSchedPtr)) { @@ -3891,6 +3904,8 @@ void GetSimpleAirModelInputs(EnergyPlusData &state, bool &ErrorsFound) // IF err ConnectionNumber = state.dataHeatBal->RefDoorMixing(ZoneNumA).NumRefDoorConnections + 1; state.dataHeatBal->RefDoorMixing(ZoneNumA).NumRefDoorConnections = ConnectionNumber; state.dataHeatBal->RefDoorMixing(ZoneNumA).ZonePtr = ZoneNumA; + state.dataHeatBal->RefDoorMixing(ZoneNumA).spaceIndex = spaceNumA; + state.dataHeatBal->RefDoorMixing(ZoneNumA).fromSpaceIndex = spaceNumB; state.dataHeatBal->RefDoorMixing(ZoneNumA).MateZonePtr(ConnectionNumber) = ZoneNumB; state.dataHeatBal->RefDoorMixing(ZoneNumA).DoorMixingObjectName(ConnectionNumber) = NameThisObject; // need to make sure same pair of zones is only entered once. diff --git a/src/EnergyPlus/ZoneEquipmentManager.cc b/src/EnergyPlus/ZoneEquipmentManager.cc index 6c4089019e1..ae3ecdf4cbd 100644 --- a/src/EnergyPlus/ZoneEquipmentManager.cc +++ b/src/EnergyPlus/ZoneEquipmentManager.cc @@ -6403,9 +6403,15 @@ void CalcAirFlowSimple(EnergyPlusData &state, // Zone loops structured in getinput so only do each pair of zones bounding door once, even if multiple doors in one zone for (int ZoneA = 1; ZoneA <= (state.dataGlobal->NumOfZones - 1); ++ZoneA) { if (!state.dataHeatBal->RefDoorMixing(ZoneA).RefDoorMixFlag) continue; + auto &thisRefDoorMixing = state.dataHeatBal->RefDoorMixing(ZoneA); auto &zoneAHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneA); Real64 TZoneA = zoneAHB.MixingMAT; Real64 HumRatZoneA = zoneAHB.MixingHumRat; + if ((state.dataHeatBal->doSpaceHeatBalance) && (thisRefDoorMixing.spaceIndex > 0)) { + auto &spaceAHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(thisRefDoorMixing.spaceIndex); + TZoneA = spaceAHB.MixingMAT; + HumRatZoneA = spaceAHB.MixingHumRat; + } Real64 AirDensityZoneA = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, TZoneA, HumRatZoneA, RoutineNameRefrigerationDoorMixing); Real64 CpAirZoneA = PsyCpAirFnW(HumRatZoneA); for (int j = 1; j <= state.dataHeatBal->RefDoorMixing(ZoneA).NumRefDoorConnections; ++j) { @@ -6414,6 +6420,11 @@ void CalcAirFlowSimple(EnergyPlusData &state, Real64 TZoneB = zoneBHB.MixingMAT; Real64 HumRatZoneB = zoneBHB.MixingHumRat; Real64 CpAirZoneB = PsyCpAirFnW(HumRatZoneB); + if ((state.dataHeatBal->doSpaceHeatBalance) && (thisRefDoorMixing.fromSpaceIndex > 0)) { + auto &spaceBHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(thisRefDoorMixing.fromSpaceIndex); + TZoneB = spaceBHB.MixingMAT; + HumRatZoneB = spaceBHB.MixingHumRat; + } Real64 Tavg = (TZoneA + TZoneB) / 2.0; Real64 Wavg = (HumRatZoneA + HumRatZoneB) / 2.0; Real64 AirDensityAvg = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, Tavg, Wavg, RoutineNameRefrigerationDoorMixing); @@ -6471,23 +6482,39 @@ void CalcAirFlowSimple(EnergyPlusData &state, zoneAHB.MixingMassFlowXHumRat += MassFlowXHumRatToA; zoneBHB.MixingMassFlowXHumRat += MassFlowXHumRatToB; if (state.dataHeatBal->doSpaceHeatBalance) { - // ZoneRefrigerationDoorMixing has no space information, just zones - // Allocate mixing flows by space volume fraction of zone volume - for (int spaceNum : state.dataHeatBal->Zone(ZoneA).spaceIndexes) { - Real64 spaceFrac = state.dataHeatBal->space(spaceNum).fracZoneVolume; - auto &spaceAHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum); - spaceAHB.MCPM += MassFlowXCpToA * spaceFrac; - spaceAHB.MCPTM += MassFlowXCpXTempToA * spaceFrac; - spaceAHB.MixingMassFlowZone += MassFlowToA * spaceFrac; - spaceAHB.MixingMassFlowXHumRat += MassFlowXHumRatToA * spaceFrac; + if (thisRefDoorMixing.spaceIndex > 0) { + auto &spaceAHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(thisRefDoorMixing.spaceIndex); + spaceAHB.MCPM += MassFlowXCpToA; + spaceAHB.MCPTM += MassFlowXCpXTempToA; + spaceAHB.MixingMassFlowZone += MassFlowToA; + spaceAHB.MixingMassFlowXHumRat += MassFlowXHumRatToA; + } else { + // Allocate mixing flows by space volume fraction of zone volume + for (int spaceNum : state.dataHeatBal->Zone(ZoneA).spaceIndexes) { + Real64 spaceFrac = state.dataHeatBal->space(spaceNum).fracZoneVolume; + auto &spaceAHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum); + spaceAHB.MCPM += MassFlowXCpToA * spaceFrac; + spaceAHB.MCPTM += MassFlowXCpXTempToA * spaceFrac; + spaceAHB.MixingMassFlowZone += MassFlowToA * spaceFrac; + spaceAHB.MixingMassFlowXHumRat += MassFlowXHumRatToA * spaceFrac; + } } - for (int spaceNum : state.dataHeatBal->Zone(ZoneB).spaceIndexes) { - Real64 spaceFrac = state.dataHeatBal->space(spaceNum).fracZoneVolume; - auto &spaceBHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum); - spaceBHB.MCPM += MassFlowXCpToB * spaceFrac; - spaceBHB.MCPTM += MassFlowXCpXTempToB * spaceFrac; - spaceBHB.MixingMassFlowZone += MassFlowToB * spaceFrac; - spaceBHB.MixingMassFlowXHumRat += MassFlowXHumRatToB * spaceFrac; + if (thisRefDoorMixing.spaceIndex > 0) { + auto &spaceBHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(thisRefDoorMixing.fromSpaceIndex); + spaceBHB.MCPM += MassFlowXCpToB; + spaceBHB.MCPTM += MassFlowXCpXTempToB; + spaceBHB.MixingMassFlowZone += MassFlowToB; + spaceBHB.MixingMassFlowXHumRat += MassFlowXHumRatToB; + } else { + // Allocate mixing flows by space volume fraction of zone volume + for (int spaceNum : state.dataHeatBal->Zone(ZoneB).spaceIndexes) { + Real64 spaceFrac = state.dataHeatBal->space(spaceNum).fracZoneVolume; + auto &spaceBHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(spaceNum); + spaceBHB.MCPM += MassFlowXCpToB * spaceFrac; + spaceBHB.MCPTM += MassFlowXCpXTempToB * spaceFrac; + spaceBHB.MixingMassFlowZone += MassFlowToB * spaceFrac; + spaceBHB.MixingMassFlowXHumRat += MassFlowXHumRatToB * spaceFrac; + } } }