diff --git a/src/EnergyPlus/DXCoils.cc b/src/EnergyPlus/DXCoils.cc index b65c0f38fd9..65933197c17 100644 --- a/src/EnergyPlus/DXCoils.cc +++ b/src/EnergyPlus/DXCoils.cc @@ -614,8 +614,8 @@ namespace EnergyPlus::DXCoils { // Determine combined performance state.dataDXCoils->DXCoil(DXCoilNum).OutletAirEnthalpy = - (1.0 - S12RuntimeFraction) * S1OutletAirEnthalpy + S12RuntimeFraction * S12OutletAirEnthalpy; - state.dataDXCoils->DXCoil(DXCoilNum).OutletAirHumRat = (1.0 - S12RuntimeFraction) * S1OutletAirHumRat + S12RuntimeFraction * S12OutletAirHumRat; + (1.0 - S2PLR) * S1OutletAirEnthalpy + S2PLR * S12OutletAirEnthalpy; + state.dataDXCoils->DXCoil(DXCoilNum).OutletAirHumRat = (1.0 - S2PLR) * S1OutletAirHumRat + S2PLR * S12OutletAirHumRat; state.dataDXCoils->DXCoil(DXCoilNum).OutletAirTemp = PsyTdbFnHW(state.dataDXCoils->DXCoil(DXCoilNum).OutletAirEnthalpy, state.dataDXCoils->DXCoil(DXCoilNum).OutletAirHumRat); // Check for saturation error and modify temperature at constant enthalpy if (state.dataDXCoils->DXCoil(DXCoilNum).CondenserInletNodeNum(PerfMode) != 0) { @@ -11835,7 +11835,6 @@ namespace EnergyPlus::DXCoils { Real64 LSElecCoolingPower; // low speed power [W] Real64 HSElecCoolingPower; // high speed power [W] Real64 CrankcaseHeatingPower; // Power due to crank case heater - Real64 Hfg; Real64 AirVolumeFlowRate; // Air volume flow rate across the heating coil Real64 VolFlowperRatedTotCap; // Air volume flow rate divided by rated total heating capacity @@ -12208,14 +12207,9 @@ namespace EnergyPlus::DXCoils { OutletAirHumRat = HSOutletAirHumRat; OutletAirDryBulbTemp = HSOutletAirDryBulbTemp; } else { - if (FanOpMode == ContFanCycCoil) { - Real64 MinAirHumRat(0.0); // set to zero because MinAirHumRat is unused argument - Hfg = PsyHfgAirFnWTdb(MinAirHumRat, HSOutletAirDryBulbTemp * SpeedRatio + (1.0 - SpeedRatio) * LSOutletAirDryBulbTemp); - // Average outlet HR - OutletAirHumRat = InletAirHumRat - state.dataDXCoils->DXCoil(DXCoilNum).LatCoolingEnergyRate / Hfg / state.dataDXCoils->DXCoil(DXCoilNum).InletAirMassFlowRate; - } else { - OutletAirHumRat = (HSOutletAirHumRat * SpeedRatio) + (LSOutletAirHumRat * (1.0 - SpeedRatio)); - } + OutletAirHumRat = + ((HSOutletAirHumRat * SpeedRatio * MSHPMassFlowRateHigh) + (LSOutletAirHumRat * (1.0 - SpeedRatio) * MSHPMassFlowRateLow)) / + state.dataDXCoils->DXCoil(DXCoilNum).InletAirMassFlowRate; OutletAirDryBulbTemp = PsyTdbFnHW(OutletAirEnthalpy, OutletAirHumRat); if (OutletAirDryBulbTemp < OutletAirDryBulbTempSat) { // Limit to saturated conditions at OutletAirEnthalpy OutletAirDryBulbTemp = OutletAirDryBulbTempSat; @@ -12241,6 +12235,9 @@ namespace EnergyPlus::DXCoils { state.dataDXCoils->DXCoil(DXCoilNum).ElecCoolingPower = state.dataDXCoils->DXCoil(DXCoilNum).CoolingCoilRuntimeFraction * HSElecCoolingPower + (1.0 - state.dataDXCoils->DXCoil(DXCoilNum).CoolingCoilRuntimeFraction) * LSElecCoolingPower; } + // Now reset runtime fraction to 1.0 (because LS is running the full timestep) + state.dataDXCoils->DXCoil(DXCoilNum).CoolingCoilRuntimeFraction = 1.0; + // Calculation for heat reclaim needs to be corrected to use compressor power (not including condenser fan power) state.dataHeatBal->HeatReclaimDXCoil(DXCoilNum).AvailCapacity = state.dataDXCoils->DXCoil(DXCoilNum).TotalCoolingEnergyRate + state.dataDXCoils->DXCoil(DXCoilNum).ElecCoolingPower; @@ -12427,10 +12424,23 @@ namespace EnergyPlus::DXCoils { } if (FanOpMode == CycFanCycCoil) state.dataHVACGlobal->OnOffFanPartLoadFraction = PLF; - // outlet conditions are average of inlet and low speed weighted by CycRatio - OutletAirEnthalpy = LSOutletAirEnthalpy; - OutletAirHumRat = LSOutletAirHumRat; - OutletAirDryBulbTemp = LSOutletAirDryBulbTemp; + if (FanOpMode == ContFanCycCoil) { + // outlet conditions are average of inlet and low speed weighted by CycRatio + // Continuous fan, cycling compressor + Real64 CycAirFlowRatio = + CycRatio * AirMassFlow / + state.dataDXCoils->DXCoil(DXCoilNum).InletAirMassFlowRate; // ratio of compressor on airflow to average timestep airflow + OutletAirEnthalpy = + CycAirFlowRatio * LSOutletAirEnthalpy + (1.0 - CycAirFlowRatio) * InletAirEnthalpy; + OutletAirHumRat = + CycAirFlowRatio * LSOutletAirHumRat + (1.0 - CycAirFlowRatio) * InletAirHumRat; + OutletAirDryBulbTemp = PsyTdbFnHW(OutletAirEnthalpy, OutletAirHumRat); + } else { + OutletAirHumRat = LSOutletAirHumRat; + OutletAirDryBulbTemp = LSOutletAirDryBulbTemp; + OutletAirEnthalpy = LSOutletAirEnthalpy; + } + // get low speed EIR at current conditions EIRTempModFacLS = CurveValue(state, state.dataDXCoils->DXCoil(DXCoilNum).MSEIRFTemp(SpeedNum), InletAirWetBulbC, CondInletTemp); EIRFlowModFacLS = CurveValue(state, state.dataDXCoils->DXCoil(DXCoilNum).MSEIRFFlow(SpeedNum), AirMassFlowRatioLS); @@ -12451,25 +12461,7 @@ namespace EnergyPlus::DXCoils { state.dataDXCoils->DXCoil(DXCoilNum).TotalCoolingEnergyRate = state.dataDXCoils->DXCoil(DXCoilNum).TotalCoolingEnergyRate * CycRatio; state.dataDXCoils->DXCoil(DXCoilNum).SensCoolingEnergyRate = state.dataDXCoils->DXCoil(DXCoilNum).SensCoolingEnergyRate * CycRatio; state.dataDXCoils->DXCoil(DXCoilNum).LatCoolingEnergyRate = state.dataDXCoils->DXCoil(DXCoilNum).LatCoolingEnergyRate * CycRatio; - if (FanOpMode == ContFanCycCoil) { - OutletAirEnthalpy = InletAirEnthalpy - state.dataDXCoils->DXCoil(DXCoilNum).TotalCoolingEnergyRate / state.dataDXCoils->DXCoil(DXCoilNum).InletAirMassFlowRate; - Real64 MinAirHumRat(0.0); // set to zero because MinAirHumRat is unused argument - Hfg = PsyHfgAirFnWTdb(MinAirHumRat, OutletAirDryBulbTemp * CycRatio + (1.0 - CycRatio) * InletAirDryBulbTemp); - OutletAirHumRat = InletAirHumRat - state.dataDXCoils->DXCoil(DXCoilNum).LatCoolingEnergyRate / Hfg / state.dataDXCoils->DXCoil(DXCoilNum).InletAirMassFlowRate; - OutletAirDryBulbTemp = PsyTdbFnHW(OutletAirEnthalpy, OutletAirHumRat); - if (OutletAirDryBulbTemp < OutletAirDryBulbTempSat) { // Limit to saturated conditions at OutletAirEnthalpy - OutletAirDryBulbTemp = OutletAirDryBulbTempSat; - OutletAirHumRat = PsyWFnTdbH(state, OutletAirDryBulbTemp, OutletAirEnthalpy, RoutineName); - CalcComponentSensibleLatentOutput(state.dataDXCoils->DXCoil(DXCoilNum).InletAirMassFlowRate, - InletAirDryBulbTemp, - InletAirHumRat, - OutletAirDryBulbTemp, - OutletAirHumRat, - state.dataDXCoils->DXCoil(DXCoilNum).SensCoolingEnergyRate, - state.dataDXCoils->DXCoil(DXCoilNum).LatCoolingEnergyRate, - state.dataDXCoils->DXCoil(DXCoilNum).TotalCoolingEnergyRate); - } - } + // Calculation for heat reclaim needs to be corrected to use compressor power (not including condenser fan power) state.dataHeatBal->HeatReclaimDXCoil(DXCoilNum).AvailCapacity = state.dataDXCoils->DXCoil(DXCoilNum).TotalCoolingEnergyRate + state.dataDXCoils->DXCoil(DXCoilNum).ElecCoolingPower; state.dataDXCoils->DXCoil(DXCoilNum).OutletAirEnthalpy = OutletAirEnthalpy; diff --git a/src/EnergyPlus/UnitarySystem.cc b/src/EnergyPlus/UnitarySystem.cc index cc5a7f3efb2..e006fd83703 100644 --- a/src/EnergyPlus/UnitarySystem.cc +++ b/src/EnergyPlus/UnitarySystem.cc @@ -2144,7 +2144,8 @@ namespace UnitarySystems { this->m_IdleSpeedRatio = this->m_IdleVolumeAirRate / this->m_DesignFanVolFlowRate; } - } else if (this->m_CoolingCoilType_Num == DataHVACGlobals::CoilDX_MultiSpeedCooling) { + } else if (this->m_CoolingCoilType_Num == DataHVACGlobals::CoilDX_MultiSpeedCooling || + this->m_CoolingCoilType_Num == DataHVACGlobals::CoilDX_CoolingTwoSpeed) { if (this->m_NumOfSpeedCooling > 0) { if (this->m_CoolVolumeFlowRate.size() == 0) this->m_CoolVolumeFlowRate.resize(this->m_NumOfSpeedCooling + 1); @@ -2183,6 +2184,15 @@ namespace UnitarySystems { this->m_IdleVolumeAirRate = this->m_MaxNoCoolHeatAirVolFlow; this->m_IdleMassFlowRate = this->MaxNoCoolHeatAirMassFlow; this->m_IdleSpeedRatio = this->m_IdleVolumeAirRate / this->m_DesignFanVolFlowRate; + } else { + for ( Iter = this->m_NumOfSpeedCooling; Iter > 0; --Iter ) { + this->m_CoolVolumeFlowRate[ Iter ] = this->m_MaxCoolAirVolFlow * Iter / this->m_NumOfSpeedCooling; + this->m_CoolMassFlowRate[ Iter ] = this->m_CoolVolumeFlowRate[ Iter ] * state.dataEnvrn->StdRhoAir; + this->m_MSCoolingSpeedRatio[ Iter ] = this->m_CoolVolumeFlowRate[ Iter ] / this->m_DesignFanVolFlowRate; + } + this->m_IdleVolumeAirRate = this->m_MaxNoCoolHeatAirVolFlow; + this->m_IdleMassFlowRate = this->m_IdleVolumeAirRate * state.dataEnvrn->StdRhoAir; + this->m_IdleSpeedRatio = this->m_IdleVolumeAirRate / this->m_DesignFanVolFlowRate; } } else if (this->m_CoolingCoilType_Num == DataHVACGlobals::Coil_CoolingWater || this->m_CoolingCoilType_Num == DataHVACGlobals::Coil_CoolingWaterDetailed) { @@ -4309,7 +4319,13 @@ namespace UnitarySystems { } else { // mine data from DX cooling coil - if (thisSys.m_CoolingCoilType_Num == DataHVACGlobals::CoilDX_CoolingTwoSpeed) thisSys.m_NumOfSpeedCooling = 2; + if (thisSys.m_CoolingCoilType_Num == DataHVACGlobals::CoilDX_CoolingTwoSpeed) { + thisSys.m_NumOfSpeedCooling = 2; + thisSys.m_MultiOrVarSpeedCoolCoil = true; + } else { + thisSys.m_NumOfSpeedCooling = 1; + thisSys.m_MultiOrVarSpeedCoolCoil = false; + } // Get DX cooling coil index DXCoils::GetDXCoilIndex(state, @@ -7083,20 +7099,7 @@ namespace UnitarySystems { { auto const SELECT_CASE_var(state.dataUnitarySystems->unitarySys[sysNum].m_CoolingCoilType_Num); - if (SELECT_CASE_var == DataHVACGlobals::CoilDX_CoolingTwoSpeed) { - SetupOutputVariable(state, "Unitary System Cycling Ratio", - OutputProcessor::Unit::None, - state.dataUnitarySystems->unitarySys[sysNum].m_CycRatio, - "System", - "Average", - state.dataUnitarySystems->unitarySys[sysNum].Name); - SetupOutputVariable(state, "Unitary System Compressor Speed Ratio", - OutputProcessor::Unit::None, - state.dataUnitarySystems->unitarySys[sysNum].m_SpeedRatio, - "System", - "Average", - state.dataUnitarySystems->unitarySys[sysNum].Name); - } else if (SELECT_CASE_var == DataHVACGlobals::CoilDX_MultiSpeedCooling || (SELECT_CASE_var == DataHVACGlobals::CoilDX_Cooling)) { + if (SELECT_CASE_var == DataHVACGlobals::CoilDX_MultiSpeedCooling || (SELECT_CASE_var == DataHVACGlobals::CoilDX_Cooling)) { if (state.dataUnitarySystems->unitarySys[sysNum].m_HeatRecActive) { SetupOutputVariable(state, "Unitary System Heat Recovery Rate", OutputProcessor::Unit::W, @@ -7181,6 +7184,7 @@ namespace UnitarySystems { } if (state.dataUnitarySystems->unitarySys[sysNum].m_CoolingCoilType_Num == DataHVACGlobals::CoilDX_MultiSpeedCooling || + state.dataUnitarySystems->unitarySys[sysNum].m_CoolingCoilType_Num == DataHVACGlobals::CoilDX_CoolingTwoSpeed || state.dataUnitarySystems->unitarySys[sysNum].m_CoolingCoilType_Num == DataHVACGlobals::CoilDX_Cooling || state.dataUnitarySystems->unitarySys[sysNum].m_HeatingCoilType_Num == DataHVACGlobals::CoilDX_MultiSpeedHeating || state.dataUnitarySystems->unitarySys[sysNum].m_HeatingCoilType_Num == DataHVACGlobals::Coil_HeatingElectric_MultiStage || @@ -8970,7 +8974,10 @@ namespace UnitarySystems { // RETURN if the moisture load is met if (state.dataUnitarySystems->MoistureLoad >= 0.0 || state.dataUnitarySystems->MoistureLoad >= TempLatOutput) return; // Multimode does not meet the latent load, only the sensible load with or without HX active + // what if there is a heating load for a system using Multimode? if (!state.dataUnitarySystems->CoolingLoad && this->m_DehumidControlType_Num == DehumCtrlType::Multimode) return; + // if HX was previously turned on return since sensible load is already met + if (state.dataUnitarySystems->CoolingLoad && this->m_DehumidControlType_Num == DehumCtrlType::Multimode && HXUnitOn) return; // IF(HeatingLoad .AND. UnitarySystem(UnitarySysNum)%m_DehumidControlType_Num .EQ. dehumidm_ControlType::CoolReheat)RETURN if ((this->m_DehumidControlType_Num == DehumCtrlType::CoolReheat || this->m_DehumidControlType_Num == DehumCtrlType::Multimode)) { diff --git a/tst/EnergyPlus/unit/HVACMultiSpeedHeatPump.unit.cc b/tst/EnergyPlus/unit/HVACMultiSpeedHeatPump.unit.cc index 1c3809ca528..e1b16bc9c32 100644 --- a/tst/EnergyPlus/unit/HVACMultiSpeedHeatPump.unit.cc +++ b/tst/EnergyPlus/unit/HVACMultiSpeedHeatPump.unit.cc @@ -1347,34 +1347,34 @@ TEST_F(EnergyPlusFixture, HVACMultiSpeedHeatPump_ReportVariableInitTest) // Check outlet conditions EXPECT_NEAR(state->dataLoopNodes->Node(22).Temp, 23.363295, 0.0001); EXPECT_NEAR(state->dataLoopNodes->Node(22).HumRat, 0.00796611, 0.0001); - EXPECT_NEAR(state->dataLoopNodes->Node(22).Enthalpy, 43744.6339, 0.0001); - EXPECT_NEAR(state->dataHVACMultiSpdHP->MSHeatPump(2).CompPartLoadRatio, 0.123500, 0.0001); + EXPECT_NEAR(state->dataLoopNodes->Node(22).Enthalpy, 43748.243, 0.0001); + EXPECT_NEAR(state->dataHVACMultiSpdHP->MSHeatPump(2).CompPartLoadRatio, 0.1232, 0.0001); // Direct solution state->dataGlobal->DoCoilDirectSolutions = true; state->dataHVACMultiSpdHP->MSHeatPump(2).FullOutput.allocate(2); SimMSHP(*state, MSHeatPumpNum, FirstHVACIteration, AirLoopNum, QSensUnitOut, QZnReq, OnOffAirFlowRatio); // Check outlet conditions - EXPECT_NEAR(state->dataLoopNodes->Node(22).Temp, 23.3641, 0.0001); - EXPECT_NEAR(state->dataLoopNodes->Node(22).HumRat, 0.00796613, 0.0001); - EXPECT_NEAR(state->dataLoopNodes->Node(22).Enthalpy, 43745.5237, 0.0001); - EXPECT_NEAR(state->dataHVACMultiSpdHP->MSHeatPump(2).CompPartLoadRatio, 0.123430, 0.0001); + EXPECT_NEAR(state->dataLoopNodes->Node(22).Temp, 23.363295, 0.0001); + EXPECT_NEAR(state->dataLoopNodes->Node(22).HumRat, 0.00796611, 0.0001); + EXPECT_NEAR(state->dataLoopNodes->Node(22).Enthalpy, 43748.243, 0.0001); + EXPECT_NEAR(state->dataHVACMultiSpdHP->MSHeatPump(2).CompPartLoadRatio, 0.1232, 0.0001); QZnReq = -10000.00; state->dataGlobal->DoCoilDirectSolutions = false; SimMSHP(*state, MSHeatPumpNum, FirstHVACIteration, AirLoopNum, QSensUnitOut, QZnReq, OnOffAirFlowRatio); - EXPECT_NEAR(state->dataLoopNodes->Node(22).Temp, 21.4545, 0.0001); + EXPECT_NEAR(state->dataLoopNodes->Node(22).Temp, 21.45298, 0.0001); EXPECT_NEAR(state->dataLoopNodes->Node(22).HumRat, 0.00792169, 0.0001); - EXPECT_NEAR(state->dataLoopNodes->Node(22).Enthalpy, 41684.8507, 0.0001); - EXPECT_NEAR(state->dataHVACMultiSpdHP->MSHeatPump(2).CompPartLoadRatio, 0.285914, 0.0001); + EXPECT_NEAR(state->dataLoopNodes->Node(22).Enthalpy, 41691.15, 0.0001); + EXPECT_NEAR(state->dataHVACMultiSpdHP->MSHeatPump(2).CompPartLoadRatio, 0.285417, 0.0001); state->dataGlobal->DoCoilDirectSolutions = true; SimMSHP(*state, MSHeatPumpNum, FirstHVACIteration, AirLoopNum, QSensUnitOut, QZnReq, OnOffAirFlowRatio); - EXPECT_NEAR(state->dataLoopNodes->Node(22).Temp, 21.4545, 0.0001); + EXPECT_NEAR(state->dataLoopNodes->Node(22).Temp, 21.45298, 0.0001); EXPECT_NEAR(state->dataLoopNodes->Node(22).HumRat, 0.00792169, 0.0001); - EXPECT_NEAR(state->dataLoopNodes->Node(22).Enthalpy, 41684.8507, 0.0001); - EXPECT_NEAR(state->dataHVACMultiSpdHP->MSHeatPump(2).CompPartLoadRatio, 0.285914, 0.0001); + EXPECT_NEAR(state->dataLoopNodes->Node(22).Enthalpy, 41691.15, 0.0001); + EXPECT_NEAR(state->dataHVACMultiSpdHP->MSHeatPump(2).CompPartLoadRatio, 0.285417, 0.0001); // Heating QZnReq = 10000.00; diff --git a/tst/EnergyPlus/unit/UnitarySystem.unit.cc b/tst/EnergyPlus/unit/UnitarySystem.unit.cc index 019cefd5fde..20c95640cf9 100644 --- a/tst/EnergyPlus/unit/UnitarySystem.unit.cc +++ b/tst/EnergyPlus/unit/UnitarySystem.unit.cc @@ -836,12 +836,12 @@ TEST_F(ZoneUnitarySysTest, Test_UnitarySystemModel_factory) EXPECT_EQ(compName, thisSys->Name); EXPECT_NEAR(100.0, thisSys->m_AncillaryOnPower, 0.00000001); EXPECT_NEAR(50.0, thisSys->m_AncillaryOffPower, 0.00000001); - EXPECT_NEAR(0.49388, thisSys->m_PartLoadFrac, 0.000001); + EXPECT_NEAR(0.488072083, thisSys->m_PartLoadFrac, 0.000001); Real64 totalAncillaryPower = thisSys->m_AncillaryOnPower * thisSys->m_PartLoadFrac + thisSys->m_AncillaryOffPower * (1.0 - thisSys->m_PartLoadFrac); EXPECT_NEAR(totalAncillaryPower, thisSys->m_TotalAuxElecPower, 0.00000001); // at PLR very near 0.5, m_TotalAuxElecPower should be very near 75 W. - EXPECT_NEAR(74.694, thisSys->m_TotalAuxElecPower, 0.0001); + EXPECT_NEAR(74.4036, thisSys->m_TotalAuxElecPower, 0.0001); } TEST_F(ZoneUnitarySysTest, UnitarySystemModel_TwoSpeedDXCoolCoil_Only)