diff --git a/src/EnergyPlus/SingleDuct.cc b/src/EnergyPlus/SingleDuct.cc index 69f03474ac6..6c49916882e 100644 --- a/src/EnergyPlus/SingleDuct.cc +++ b/src/EnergyPlus/SingleDuct.cc @@ -2877,8 +2877,15 @@ void SingleDuctAirTerminal::SizeSys(EnergyPlusData &state) CheckZoneSizing(state, this->sysType, this->SysName); - MaxAirVolFlowRateDes = max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolVolFlow, - state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow); + Real64 heatingMaxFlow; + if (this->DamperHeatingAction == Action::ReverseWithLimits && + state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow > + state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlowMax) { + heatingMaxFlow = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlowMax; + } else { + heatingMaxFlow = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow; + } + MaxAirVolFlowRateDes = max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolVolFlow, heatingMaxFlow); if (MaxAirVolFlowRateDes < SmallAirVolFlow) { MaxAirVolFlowRateDes = 0.0; @@ -2927,7 +2934,13 @@ void SingleDuctAirTerminal::SizeSys(EnergyPlusData &state) } } else { CheckZoneSizing(state, this->sysType, this->SysName); - MaxHeatAirVolFlowRateDes = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow; + if (this->DamperHeatingAction == Action::ReverseWithLimits && + state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow > + state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlowMax) { + MaxHeatAirVolFlowRateDes = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlowMax; + } else { + MaxHeatAirVolFlowRateDes = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow; + } if (MaxHeatAirVolFlowRateDes < SmallAirVolFlow) { MaxHeatAirVolFlowRateDes = 0.0; } @@ -3215,7 +3228,13 @@ void SingleDuctAirTerminal::SizeSys(EnergyPlusData &state) if (state.dataSize->ZoneSizingRunDone) { if (state.dataSize->CurTermUnitSizingNum > 0) { // if zone sizing run done, set the design max reheat air flow to the value from the design calcs - MaxAirVolFlowRateDuringReheatDes = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlowMax; + if (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow > + state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlowMax) { + MaxAirVolFlowRateDuringReheatDes = + state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlowMax; + } else { + MaxAirVolFlowRateDuringReheatDes = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow; + } } } else { // if no design calc use 0.002032 [m3/s-m2] times floor area. That's .40 cfm/ft2 @@ -3411,9 +3430,14 @@ void SingleDuctAirTerminal::SizeSys(EnergyPlusData &state) max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesHeatVolFlow, this->MaxAirVolFlowRate * this->ZoneTurndownMinAirFrac); } else { - TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow = - max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesHeatVolFlow, - this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac); + if (this->SysType_Num == SysType::SingleDuctVAVReheat && this->DamperHeatingAction == Action::ReverseWithLimits) { + TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow = + max(this->MaxAirVolFlowRateDuringReheat, this->MaxAirVolFlowRate * this->ZoneTurndownMinAirFrac); + } else { + TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow = + max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesHeatVolFlow, + this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac); + } } } else { if (this->SysType_Num == SysType::SingleDuctVAVReheatVSFan) { diff --git a/tst/EnergyPlus/unit/SingleDuct.unit.cc b/tst/EnergyPlus/unit/SingleDuct.unit.cc index 3c448d7b1ee..be5edc2ff84 100644 --- a/tst/EnergyPlus/unit/SingleDuct.unit.cc +++ b/tst/EnergyPlus/unit/SingleDuct.unit.cc @@ -1282,7 +1282,7 @@ TEST_F(EnergyPlusFixture, SingleDuct_ZeroFloorAreaTest) // zone floor area of zone 1 = 0, zone 2 > 0. Expect TU MaxAirVolFlowRateDuringReheat = 0 only for zone 1. // this test isn't relevant anymore since defaulting is done differently Real64 MaxAirVolFlowRateDuringReheatDes = - min(state->dataSize->FinalZoneSizing(1).DesHeatVolFlowMax, state->dataSingleDuct->sd_airterminal(1).MaxAirVolFlowRate); + min(state->dataSize->FinalZoneSizing(1).DesHeatVolFlow, state->dataSingleDuct->sd_airterminal(1).MaxAirVolFlowRate); // Real64 MaxAirVolFlowRateDuringReheatDes = min( 0.002032 * state->dataSingleDuct->sd_airterminal( 1 ).ZoneFloorArea, // state->dataSingleDuct->sd_airterminal( 1 ).MaxAirVolFlowRate ); apply limit based on min stop MaxAirVolFlowRateDuringReheatDes = @@ -1291,7 +1291,7 @@ TEST_F(EnergyPlusFixture, SingleDuct_ZeroFloorAreaTest) // This isn't relevant any more since the default is calculated differently Real64 MaxAirVolFractionDuringReheatDes = - min(1.0, (state->dataSize->FinalZoneSizing(1).DesHeatVolFlowMax / state->dataSingleDuct->sd_airterminal(1).MaxAirVolFlowRate)); + min(1.0, (state->dataSize->FinalZoneSizing(1).DesHeatVolFlow / state->dataSingleDuct->sd_airterminal(1).MaxAirVolFlowRate)); // Real64 MaxAirVolFractionDuringReheatDes = min( 1.0, ( 0.002032 * state->dataSingleDuct->sd_airterminal( 1 ).ZoneFloorArea / // state->dataSingleDuct->sd_airterminal( 1 ).MaxAirVolFlowRate ) // ); apply limit based on min stop @@ -1306,12 +1306,12 @@ TEST_F(EnergyPlusFixture, SingleDuct_ZeroFloorAreaTest) EXPECT_NEAR(MaxAirVolFractionDuringReheatDes, state->dataSingleDuct->sd_airterminal(1).MaxAirVolFractionDuringReheat, 0.0000000000001); MaxAirVolFlowRateDuringReheatDes = - min(state->dataSize->FinalZoneSizing(2).DesHeatVolFlowMax, state->dataSingleDuct->sd_airterminal(2).MaxAirVolFlowRate); + min(state->dataSize->FinalZoneSizing(2).DesHeatVolFlow, state->dataSingleDuct->sd_airterminal(2).MaxAirVolFlowRate); MaxAirVolFlowRateDuringReheatDes = max(MaxAirVolFlowRateDuringReheatDes, (state->dataSingleDuct->sd_airterminal(2).MaxAirVolFlowRate * state->dataSingleDuct->sd_airterminal(2).ZoneMinAirFrac)); MaxAirVolFractionDuringReheatDes = - min(1.0, (state->dataSize->FinalZoneSizing(2).DesHeatVolFlowMax / state->dataSingleDuct->sd_airterminal(2).MaxAirVolFlowRate)); + min(1.0, (state->dataSize->FinalZoneSizing(2).DesHeatVolFlow / state->dataSingleDuct->sd_airterminal(2).MaxAirVolFlowRate)); MaxAirVolFractionDuringReheatDes = max(MaxAirVolFractionDuringReheatDes, state->dataSingleDuct->sd_airterminal(2).ZoneMinAirFrac); MaxAirVolFlowRateDuringReheatDes = min(max(MaxAirVolFlowRateDuringReheatDes, MaxAirVolFractionDuringReheatDes * state->dataSingleDuct->sd_airterminal(2).MaxAirVolFlowRate), @@ -2737,23 +2737,69 @@ TEST_F(EnergyPlusFixture, VAVReheatTerminal_SizeMinFrac) EXPECT_TRUE(compare_err_stream("")); int SysNum = 1; + auto &thisSys = state->dataSingleDuct->sd_airterminal(SysNum); // First test - design min flow < max flow state->dataSize->ZoneSizingRunDone = true; state->dataSize->CurZoneEqNum = 1; state->dataSize->CurTermUnitSizingNum = 1; state->dataSize->TermUnitFinalZoneSizing(1).DesCoolVolFlowMin = 0.5; - state->dataSingleDuct->sd_airterminal(SysNum).SizeSys(*state); - EXPECT_EQ(0.5, state->dataSingleDuct->sd_airterminal(SysNum).ZoneMinAirFracDes); + thisSys.SizeSys(*state); + EXPECT_EQ(0.5, thisSys.ZoneMinAirFracDes); // Second test - design min flow > max flow state->dataSize->ZoneSizingRunDone = true; state->dataSize->CurZoneEqNum = 1; state->dataSize->CurTermUnitSizingNum = 1; - state->dataSingleDuct->sd_airterminal(SysNum).ZoneMinAirFracDes = AutoSize; // need to reset this so it sizes again + thisSys.ZoneMinAirFracDes = AutoSize; // need to reset this so it sizes again state->dataSize->TermUnitFinalZoneSizing(1).DesCoolVolFlowMin = 1.5; - state->dataSingleDuct->sd_airterminal(SysNum).SizeSys(*state); - EXPECT_EQ(1.0, state->dataSingleDuct->sd_airterminal(SysNum).ZoneMinAirFracDes); + thisSys.SizeSys(*state); + EXPECT_EQ(1.0, thisSys.ZoneMinAirFracDes); + + // test Maximum Flow Fraction During Reheat for heating dominated + thisSys.MaxAirVolFlowRate = DataSizing::AutoSize; + thisSys.ZoneMinAirFracDes = DataSizing::AutoSize; + thisSys.MaxAirVolFlowRateDuringReheat = DataSizing::AutoSize; + thisSys.MaxAirVolFractionDuringReheat = DataSizing::AutoSize; + state->dataSize->TermUnitFinalZoneSizing(1).DesHeatVolFlow = 1.7; + state->dataSize->TermUnitFinalZoneSizing(1).DesHeatVolFlowMax = 1.6; + thisSys.SizeSys(*state); + Real64 expectedZoneMinAirFracDes = std::min(1.0, state->dataSize->TermUnitFinalZoneSizing(1).DesCoolVolFlowMin / thisSys.MaxAirVolFlowRate); + // DesHeatVolFlowMax is limiting flow rate + Real64 expectedMaxAirVolFractionDuringReheat = state->dataSize->TermUnitFinalZoneSizing(1).DesHeatVolFlowMax / thisSys.MaxAirVolFlowRate; + EXPECT_EQ(expectedZoneMinAirFracDes, thisSys.ZoneMinAirFracDes); + EXPECT_EQ(1.0, thisSys.MaxAirVolFractionDuringReheat); + EXPECT_EQ(expectedMaxAirVolFractionDuringReheat, thisSys.MaxAirVolFractionDuringReheat); + + // switch magnitude of DesHeatVolFlow and DesHeatVolFlowMax, still heating dominated + thisSys.MaxAirVolFlowRate = DataSizing::AutoSize; + thisSys.ZoneMinAirFracDes = DataSizing::AutoSize; + thisSys.MaxAirVolFlowRateDuringReheat = DataSizing::AutoSize; + thisSys.MaxAirVolFractionDuringReheat = DataSizing::AutoSize; + state->dataSize->TermUnitFinalZoneSizing(1).DesHeatVolFlow = 1.6; + state->dataSize->TermUnitFinalZoneSizing(1).DesHeatVolFlowMax = 1.7; + thisSys.SizeSys(*state); + expectedZoneMinAirFracDes = std::min(1.0, state->dataSize->TermUnitFinalZoneSizing(1).DesCoolVolFlowMin / thisSys.MaxAirVolFlowRate); + // DesHeatVolFlowMax is NOT limiting flow rate + expectedMaxAirVolFractionDuringReheat = state->dataSize->TermUnitFinalZoneSizing(1).DesHeatVolFlow / thisSys.MaxAirVolFlowRate; + EXPECT_EQ(expectedZoneMinAirFracDes, thisSys.ZoneMinAirFracDes); + EXPECT_EQ(1.0, thisSys.MaxAirVolFractionDuringReheat); + EXPECT_EQ(expectedMaxAirVolFractionDuringReheat, thisSys.MaxAirVolFractionDuringReheat); + + // test Maximum Flow Fraction During Reheat for cooling dominated + thisSys.MaxAirVolFlowRate = DataSizing::AutoSize; + thisSys.ZoneMinAirFracDes = DataSizing::AutoSize; + thisSys.MaxAirVolFlowRateDuringReheat = DataSizing::AutoSize; + thisSys.MaxAirVolFractionDuringReheat = DataSizing::AutoSize; + state->dataSize->TermUnitFinalZoneSizing(1).DesHeatVolFlow = 1.4; + state->dataSize->TermUnitFinalZoneSizing(1).DesHeatVolFlowMax = 1.3; + thisSys.SizeSys(*state); + expectedZoneMinAirFracDes = std::min(1.0, state->dataSize->TermUnitFinalZoneSizing(1).DesCoolVolFlowMin / thisSys.MaxAirVolFlowRate); + // DesHeatVolFlowMax is limiting flow rate + expectedMaxAirVolFractionDuringReheat = state->dataSize->TermUnitFinalZoneSizing(1).DesHeatVolFlowMax / thisSys.MaxAirVolFlowRate; + EXPECT_EQ(expectedZoneMinAirFracDes, thisSys.ZoneMinAirFracDes); + EXPECT_EQ(1.0, thisSys.MaxAirVolFractionDuringReheat); + EXPECT_EQ(expectedMaxAirVolFractionDuringReheat, thisSys.MaxAirVolFractionDuringReheat); } TEST_F(EnergyPlusFixture, setATMixerSizingProperties_Test) diff --git a/tst/EnergyPlus/unit/VAVDefMinMaxFlow.unit.cc b/tst/EnergyPlus/unit/VAVDefMinMaxFlow.unit.cc index e4307f6da2d..d7ff4369e02 100644 --- a/tst/EnergyPlus/unit/VAVDefMinMaxFlow.unit.cc +++ b/tst/EnergyPlus/unit/VAVDefMinMaxFlow.unit.cc @@ -490,8 +490,12 @@ TEST_F(EnergyPlusFixture, VAVDefMinMaxFlowTestSizing2) state->dataSingleDuct->sd_airterminal(1).ZoneFloorArea = state->dataHeatBal->Zone(1).FloorArea; UpdateTermUnitFinalZoneSizing(*state); // Fills the TermUnitFinalZoneSizing array state->dataSingleDuct->sd_airterminal(1).SizeSys(*state); + Real64 heatVolFlow = (state->dataSize->FinalZoneSizing(state->dataSize->CurZoneEqNum).DesHeatVolFlow > + state->dataSize->FinalZoneSizing(state->dataSize->CurZoneEqNum).DesHeatVolFlowMax) + ? state->dataSize->FinalZoneSizing(state->dataSize->CurZoneEqNum).DesHeatVolFlowMax + : state->dataSize->FinalZoneSizing(state->dataSize->CurZoneEqNum).DesHeatVolFlow; EXPECT_NEAR(state->dataSingleDuct->sd_airterminal(state->dataSize->CurZoneEqNum).ZoneMinAirFracDes, 0.348739, 0.000001); - EXPECT_NEAR(state->dataSingleDuct->sd_airterminal(state->dataSize->CurZoneEqNum).MaxAirVolFlowRateDuringReheat, 0.196047, 0.000001); + EXPECT_NEAR(state->dataSingleDuct->sd_airterminal(state->dataSize->CurZoneEqNum).MaxAirVolFlowRateDuringReheat, heatVolFlow, 0.000001); state->dataLoopNodes->Node.deallocate(); state->dataZoneEquip->ZoneEquipConfig.deallocate();