diff --git a/idd/Energy+.idd.in b/idd/Energy+.idd.in index 40ed2734609..675848cbd24 100644 --- a/idd/Energy+.idd.in +++ b/idd/Energy+.idd.in @@ -73383,21 +73383,13 @@ Chiller:Electric:EIR, \note PLR is the chilled water plant loop part load ratio (actual/design) \type object-list \object-list UnivariateFunctions - N19, \field Temperature Difference Across Condenser - \type real - \units C - \minimum 2.0 - \default 15.0 - \note The temperature difference across the condenser. This input is used to calculate the condenser flow - \note request.This input is only used when "Condenser Flow Control" is set to - \note "ModulatedDeltaTemperature". A20, \field Temperature Difference Across Condenser Schedule Name \note A schedule that defines the temperature difference across the condenser. This input is used to \note calculate the condenser flow. This input is only used when "Condenser Flow Control" is set to \note "ModulatedDeltaTemperature". \type object-list \object-list ScheduleNames - N20; \field Condenser Minimum Flow Fraction + N19; \field Condenser Minimum Flow Fraction \note This input corresponds to the minimum flow fraction to be simulated. The minimum condenser flow \note corresponds to this fraction multiplied by the maximum condenser flow rate. This input is only used \note when the "Condenser Flow Control" input is set to "ModulatedChillerPLR", "ModulatedLoopPLR" or @@ -73595,11 +73587,48 @@ Chiller:Electric:ReformulatedEIR, \note Using this triggers a model more suited to series bundle and chillers with higher temperature heat recovery \note If this field is not used, the bundles are modeled as being in parallel \type node - A15; \field End-Use Subcategory + A15, \field End-Use Subcategory \note Any text may be used here to categorize the end-uses in the ABUPS End Uses by Subcategory table. \type alpha \retaincase \default General + A16, \field Condenser Flow Control + \note Select the chiller condenser flow request mode. With "ConstantFlow" a chiller will always request + \note its maximum condenser flow rate. With "ModulatedChillerPLR" the condenser flow request corresponds + \note to the chiller part load ratio multiplied by the chiller maximum condenser flow rate. With + \note "ModulatedLoopPLR" the chiller will request a flow rate that is function of the chilled water + \note loop's part load ratio, see the "Condenser Loop Flow Rate Fraction Function of Loop Part Load Ratio + \note Curve Name" input. With "ModulatedDeltaTemperature" the chiller will request the flow rate required to meet + \note the condenser loop load based on the condenser leaving fluid temperature and a reference temperature, + \note see the "Temperature Difference Across Condenser" and "Temperature Difference Across Condenser Schedule + \note Name" input. + \note Use "ConstantFlow" when modeling a constant flow condenser plant loop, choose one of the other inputs + \note when modeling a variable flow condenser plant loop. + \key ConstantFlow + \key ModulatedChillerPLR + \key ModulatedLoopPLR + \key ModulatedDeltaTemperature + \default ConstantFlow + A17, \field Condenser Loop Flow Rate Fraction Function of Loop Part Load Ratio Curve Name + \note Condenser loop flow rate fraction as a function of loop part load ratio + \note CWFR = C * PLR + D + \note Where: + \note CWFR is the condenser water flow fraction (actual/design) + \note C and D are coefficients, see "Optimizing Design & Control Of Chilled Water Plants, Part 5", S. Taylor, ASHRAE Journal June 2012 + \note PLR is the chilled water plant loop part load ratio (actual/design) + \type object-list + \object-list UnivariateFunctions + A19, \field Temperature Difference Across Condenser Schedule Name + \note A schedule that defines the temperature difference across the condenser. This input is used to + \note calculate the condenser flow. This input is only used when "Condenser Flow Control" is set to + \note "ModulatedDeltaTemperature". + \type object-list + \object-list ScheduleNames + N16; \field Condenser Minimum Flow Fraction + \note This input corresponds to the minimum flow fraction to be simulated. The minimum condenser flow + \note corresponds to this fraction multiplied by the maximum condenser flow rate. This input is only used + \note when the "Condenser Flow Control" input is set to "ModulatedChillerPLR", "ModulatedLoopPLR" or + \note "ModulatedDeltaTemperature". Chiller:Electric, \min-fields 27 diff --git a/src/EnergyPlus/ChillerElectricEIR.cc b/src/EnergyPlus/ChillerElectricEIR.cc index eeff28236e8..cf16511ce69 100644 --- a/src/EnergyPlus/ChillerElectricEIR.cc +++ b/src/EnergyPlus/ChillerElectricEIR.cc @@ -665,7 +665,7 @@ void GetElectricEIRChillerInput(EnergyPlusData &state) if (thisChiller.CondenserFlowControl == DataPlant::CondenserFlowControl::Invalid) { ShowSevereError(state, format("{}{}=\"{}\",", RoutineName, state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1))); - ShowContinueError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(10), state.dataIPShortCut->cAlphaArgs(10))); + ShowContinueError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(17), state.dataIPShortCut->cAlphaArgs(17))); ShowContinueError(state, "Available choices are ConstantFlow, ModulatedChillerPLR, ModulatedLoopPLR, or ModulatedDeltaTemperature"); ShowContinueError(state, "Flow mode ConstantFlow is assumed and the simulation continues."); thisChiller.CondenserFlowControl = DataPlant::CondenserFlowControl::ConstantFlow; @@ -685,12 +685,6 @@ void GetElectricEIRChillerInput(EnergyPlusData &state) ErrorsFound = true; } - if (NumNums > 18) { - thisChiller.CondDT = state.dataIPShortCut->rNumericArgs(19); - } else { - thisChiller.CondDT = 0.0; - } - if (NumAlphas > 18) { if (!state.dataIPShortCut->lAlphaFieldBlanks(19)) { thisChiller.CondDTScheduleNum = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(19)); @@ -2418,15 +2412,6 @@ void ElectricEIRChillerSpecs::calculate(EnergyPlusData &state, Real64 &MyLoad, b PlantUtilities::SetComponentFlowRate(state, this->CondMassFlowRate, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc); PlantUtilities::PullCompInterconnectTrigger( state, this->CWPlantLoc, this->CondMassFlowIndex, this->CDPlantLoc, DataPlant::CriteriaType::MassFlowRate, this->CondMassFlowRate); - - if (this->CondMassFlowRate < DataBranchAirLoopPlant::MassFlowTolerance) { - if (this->EvapMassFlowRate < DataBranchAirLoopPlant::MassFlowTolerance) { - // Use PlantUtilities::SetComponentFlowRate to decide actual flow - PlantUtilities::SetComponentFlowRate( - state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc); - } - return; - } } if (this->CondenserType == DataPlant::CondenserType::WaterCooled) { diff --git a/src/EnergyPlus/ChillerReformulatedEIR.cc b/src/EnergyPlus/ChillerReformulatedEIR.cc index 703882e2769..104056f986a 100644 --- a/src/EnergyPlus/ChillerReformulatedEIR.cc +++ b/src/EnergyPlus/ChillerReformulatedEIR.cc @@ -628,6 +628,59 @@ void GetElecReformEIRChillerInput(EnergyPlusData &state) } else { thisChiller.EndUseSubcategory = "General"; } + + if (NumAlphas > 15) { + thisChiller.CondenserFlowControl = static_cast( + getEnumValue(DataPlant::CondenserFlowControlNamesUC, state.dataIPShortCut->cAlphaArgs(16))); + } else { + thisChiller.CondenserFlowControl = DataPlant::CondenserFlowControl::ConstantFlow; + } + + if (thisChiller.CondenserFlowControl == DataPlant::CondenserFlowControl::Invalid) { + ShowSevereError(state, + format("{}{}=\"{}\",", RoutineName, state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1))); + ShowContinueError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(16), state.dataIPShortCut->cAlphaArgs(16))); + ShowContinueError(state, "Available choices are ConstantFlow, ModulatedChillerPLR, ModulatedLoopPLR, or ModulatedDeltaTemperature"); + ShowContinueError(state, "Flow mode ConstantFlow is assumed and the simulation continues."); + thisChiller.CondenserFlowControl = DataPlant::CondenserFlowControl::ConstantFlow; + ErrorsFound = true; + }; + + if (NumAlphas > 16) { + thisChiller.ChillerCondLoopFlowFLoopPLRIndex = Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(17)); + } else { + thisChiller.ChillerCondLoopFlowFLoopPLRIndex = 0; + } + if ((thisChiller.ChillerCondLoopFlowFLoopPLRIndex == 0) && + (thisChiller.CondenserFlowControl == DataPlant::CondenserFlowControl::ModulatedLoopPLR)) { + ShowSevereError(state, + format("{}{} \"{}\"", RoutineName, state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1))); + ShowContinueError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(17), state.dataIPShortCut->cAlphaArgs(17))); + ErrorsFound = true; + } + + if (NumAlphas > 17) { + if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { + thisChiller.CondDTScheduleNum = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(18)); + if (thisChiller.CondDTScheduleNum == 0) { + ShowSevereError( + state, format("{}{}=\"{}\"", RoutineName, state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1))); + ShowContinueError(state, + format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(18), state.dataIPShortCut->cAlphaArgs(18))); + ErrorsFound = true; + } + } else { + thisChiller.CondDTScheduleNum = 0; + } + } else { + thisChiller.CondDTScheduleNum = 0; + } + + if (NumNums > 16) { + thisChiller.MinCondFlowRatio = state.dataIPShortCut->rNumericArgs(17); + } else { + thisChiller.MinCondFlowRatio = 0.2; + } } if (ErrorsFound) { @@ -2076,8 +2129,7 @@ void ReformulatedEIRChillerSpecs::calculate(EnergyPlusData &state, Real64 &MyLoa ReferenceCOP = ReferenceCOP_ff * this->FaultyChillerFoulingFactor; } - // Set mass flow rates - + // Set initial mass flow rates if (this->CondenserType == DataPlant::CondenserType::WaterCooled) { this->CondMassFlowRate = this->CondMassFlowRateMax; PlantUtilities::SetComponentFlowRate(state, this->CondMassFlowRate, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc); @@ -2439,6 +2491,69 @@ void ReformulatedEIRChillerSpecs::calculate(EnergyPlusData &state, Real64 &MyLoa this->QCondenser = this->Power * this->CompPowerToCondenserFrac + this->QEvaporator + this->ChillerFalseLoadRate; + // set condenser mass flow rate + if (this->CondenserType == DataPlant::CondenserType::WaterCooled) { + switch (this->CondenserFlowControl) { + case DataPlant::CondenserFlowControl::ConstantFlow: { + this->CondMassFlowRate = this->CondMassFlowRateMax; + } break; + case DataPlant::CondenserFlowControl::ModulatedChillerPLR: { + this->CondMassFlowRate = this->CondMassFlowRateMax * PartLoadRat; + } break; + case DataPlant::CondenserFlowControl::ModulatedLoopPLR: { + int PltSizNum = state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).PlantSizNum; + int CondPltSizNum = state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).PlantSizNum; + if (PltSizNum > 0 && CondPltSizNum > 0) { + Real64 chwLoopCap = state.dataSize->PlantSizData(PltSizNum).DesCapacity; + Real64 chwLoopDemand = + std::abs(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).UpdatedDemandToLoopSetPoint); + Real64 cwhLoopPLR = 0.0; + if (chwLoopDemand > 0) { + cwhLoopPLR = chwLoopDemand / chwLoopCap; + } + Real64 condWaterFlowFrac = Curve::CurveValue(state, this->ChillerCondLoopFlowFLoopPLRIndex, cwhLoopPLR); + Real64 cwLoopDesVolFlowRate = state.dataSize->PlantSizData(CondPltSizNum).DesVolFlowRate; + Real64 cwLoopVolFlowRate = condWaterFlowFrac * cwLoopDesVolFlowRate; + Real64 rho = FluidProperties::GetDensityGlycol(state, + state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName, + this->TempRefCondIn, + state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex, + RoutineName); + if (chwLoopDemand > 0) { + this->CondMassFlowRate = cwLoopVolFlowRate * rho * this->QEvaporator / chwLoopDemand; + } else { + this->CondMassFlowRate = 0.0; + } + } else { + ShowFatalError(state, + "CalcElectricEIRChillerModel: The ModulatedLoopPLR condenser flow control requires a Sizing:Plant object for " + "both loops connected to the condenser and evaporator of the chiller."); + } + } break; + case DataPlant::CondenserFlowControl::ModulatedDeltaTemperature: { + Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state, + state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName, + Constant::CWInitConvTemp, + state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex, + RoutineName); + Real64 condDT = 0.0; + if (this->CondDTScheduleNum > 0) { + condDT = ScheduleManager::GetCurrentScheduleValue(state, this->CondDTScheduleNum); + } else { + condDT = this->CondDT; + } + this->CondMassFlowRate = this->QCondenser / (Cp * condDT); + } break; + default: { + this->CondMassFlowRate = this->CondMassFlowRateMax; + } break; + } + this->CondMassFlowRate = max(min(this->CondMassFlowRate, this->CondMassFlowRateMax), this->MinCondFlowRatio * this->CondMassFlowRateMax); + PlantUtilities::SetComponentFlowRate(state, this->CondMassFlowRate, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc); + PlantUtilities::PullCompInterconnectTrigger( + state, this->CWPlantLoc, this->CondMassFlowIndex, this->CDPlantLoc, DataPlant::CriteriaType::MassFlowRate, this->CondMassFlowRate); + } + // Currently only water cooled chillers are allowed for the reformulated EIR chiller model if (this->CondMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) { // If Heat Recovery specified for this vapor compression chiller, then Qcondenser will be adjusted by this subroutine diff --git a/src/EnergyPlus/ChillerReformulatedEIR.hh b/src/EnergyPlus/ChillerReformulatedEIR.hh index 050c0f60a8e..20a6b5f2212 100644 --- a/src/EnergyPlus/ChillerReformulatedEIR.hh +++ b/src/EnergyPlus/ChillerReformulatedEIR.hh @@ -82,30 +82,31 @@ namespace ChillerReformulatedEIR { std::string EIRFTName; // EIRFT curve name std::string EIRFPLRName; // EIRPLR curve name DataPlant::CondenserType CondenserType = - DataPlant::CondenserType::Invalid; // Type of Condenser. Water Cooled is the only available option for now - PLR PartLoadCurveType = PLR::Invalid; // Part Load Ratio Curve Type: 1_LeavingCondenserWaterTemperature; 2_Lift - Real64 RefCap = 0.0; // Reference capacity of the chiller [W] - bool RefCapWasAutoSized = false; // reference capacity was autosized on input - Real64 RefCOP = 0.0; // Reference coefficient of performance [W/W] - DataPlant::FlowMode FlowMode = DataPlant::FlowMode::Invalid; // one of 3 modes for component flow during operation - bool ModulatedFlowSetToLoop = false; // True if the setpoint is missing at the outlet node - bool ModulatedFlowErrDone = false; // true if setpoint warning issued - Real64 EvapVolFlowRate = 0.0; // Reference water volumetric flow rate through the evaporator [m3/s] - bool EvapVolFlowRateWasAutoSized = false; // true if previous was autosize input - Real64 EvapMassFlowRateMax = 0.0; // Reference water mass flow rate through evaporator [kg/s] - Real64 CondVolFlowRate = 0.0; // Reference water volumetric flow rate through the condenser [m3/s] - bool CondVolFlowRateWasAutoSized = false; // true if previous was set to autosize on input - Real64 CondMassFlowRateMax = 0.0; // Reference water mass flow rate through condenser [kg/s] - Real64 CompPowerToCondenserFrac = 0.0; // Fraction of compressor electric power rejected by condenser [0 to 1] - int EvapInletNodeNum = 0; // Node number on the inlet side of the plant (evaporator side) - int EvapOutletNodeNum = 0; // Node number on the outlet side of the plant (evaporator side) - int CondInletNodeNum = 0; // Node number on the inlet side of the condenser - int CondOutletNodeNum = 0; // Node number on the outlet side of the condenser - Real64 MinPartLoadRat = 0.0; // Minimum allowed operating fraction of full load - Real64 MaxPartLoadRat = 0.0; // Maximum allowed operating fraction of full load - Real64 OptPartLoadRat = 0.0; // Optimal operating fraction of full load - Real64 MinUnloadRat = 0.0; // Minimum unloading ratio - Real64 TempRefCondIn = 0.0; // The reference secondary loop fluid temperature at the + DataPlant::CondenserType::Invalid; // Type of Condenser. Water Cooled is the only available option for now + PLR PartLoadCurveType = PLR::Invalid; // Part Load Ratio Curve Type: 1_LeavingCondenserWaterTemperature; 2_Lift + Real64 RefCap = 0.0; // Reference capacity of the chiller [W] + bool RefCapWasAutoSized = false; // reference capacity was autosized on input + Real64 RefCOP = 0.0; // Reference coefficient of performance [W/W] + DataPlant::FlowMode FlowMode = DataPlant::FlowMode::Invalid; + DataPlant::CondenserFlowControl CondenserFlowControl = DataPlant::CondenserFlowControl::Invalid; + bool ModulatedFlowSetToLoop = false; // True if the setpoint is missing at the outlet node + bool ModulatedFlowErrDone = false; // true if setpoint warning issued + Real64 EvapVolFlowRate = 0.0; // Reference water volumetric flow rate through the evaporator [m3/s] + bool EvapVolFlowRateWasAutoSized = false; // true if previous was autosize input + Real64 EvapMassFlowRateMax = 0.0; // Reference water mass flow rate through evaporator [kg/s] + Real64 CondVolFlowRate = 0.0; // Reference water volumetric flow rate through the condenser [m3/s] + bool CondVolFlowRateWasAutoSized = false; // true if previous was set to autosize on input + Real64 CondMassFlowRateMax = 0.0; // Reference water mass flow rate through condenser [kg/s] + Real64 CompPowerToCondenserFrac = 0.0; // Fraction of compressor electric power rejected by condenser [0 to 1] + int EvapInletNodeNum = 0; // Node number on the inlet side of the plant (evaporator side) + int EvapOutletNodeNum = 0; // Node number on the outlet side of the plant (evaporator side) + int CondInletNodeNum = 0; // Node number on the inlet side of the condenser + int CondOutletNodeNum = 0; // Node number on the outlet side of the condenser + Real64 MinPartLoadRat = 0.0; // Minimum allowed operating fraction of full load + Real64 MaxPartLoadRat = 0.0; // Maximum allowed operating fraction of full load + Real64 OptPartLoadRat = 0.0; // Optimal operating fraction of full load + Real64 MinUnloadRat = 0.0; // Minimum unloading ratio + Real64 TempRefCondIn = 0.0; // The reference secondary loop fluid temperature at the // chiller condenser side inlet for the reformulated chiller [C] Real64 TempRefCondOut = 0.0; // The reference secondary loop fluid temperature at the // chiller condenser side outlet for the reformulated chiller [C] @@ -195,22 +196,26 @@ namespace ChillerReformulatedEIR { Real64 HeatRecOutletTemp = 0.0; Real64 QHeatRecovery = 0.0; // Heat recovered from water-cooled condenser [W] Real64 QCondenser = 0.0; - Real64 QEvaporator = 0.0; // Evaporator heat transfer rate [W] - Real64 Power = 0.0; // Chiller power [W] - Real64 EvapOutletTemp = 0.0; // Evaporator outlet temperature [C] - Real64 CondOutletTemp = 0.0; // Condenser outlet temperature [C] - Real64 EvapMassFlowRate = 0.0; // Evaporator mass flow rate [kg/s] - Real64 CondMassFlowRate = 0.0; // Condenser mass flow rate [kg/s] - Real64 ChillerFalseLoad = 0.0; // Chiller false load over and above water side load [W] - Real64 Energy = 0.0; // Chiller electric consumption [J] - Real64 EvapEnergy = 0.0; // Evaporator heat transfer energy [J] - Real64 CondEnergy = 0.0; // Condenser heat transfer energy [J] - Real64 CondInletTemp = 0.0; // Condenser inlet temperature [C] - Real64 EvapInletTemp = 0.0; // Evaporator inlet temperature [C] - Real64 ActualCOP = 0.0; // Coefficient of performance - Real64 EnergyHeatRecovery = 0.0; // Energy recovered from water-cooled condenser [J] - Real64 HeatRecInletTemp = 0.0; // Heat reclaim inlet temperature [C] - Real64 HeatRecMassFlow = 0.0; // Heat reclaim mass flow rate [kg/s] + Real64 QEvaporator = 0.0; // Evaporator heat transfer rate [W] + Real64 Power = 0.0; // Chiller power [W] + Real64 EvapOutletTemp = 0.0; // Evaporator outlet temperature [C] + Real64 CondOutletTemp = 0.0; // Condenser outlet temperature [C] + Real64 EvapMassFlowRate = 0.0; // Evaporator mass flow rate [kg/s] + Real64 CondMassFlowRate = 0.0; // Condenser mass flow rate [kg/s] + Real64 ChillerFalseLoad = 0.0; // Chiller false load over and above water side load [W] + Real64 Energy = 0.0; // Chiller electric consumption [J] + Real64 EvapEnergy = 0.0; // Evaporator heat transfer energy [J] + Real64 CondEnergy = 0.0; // Condenser heat transfer energy [J] + Real64 CondInletTemp = 0.0; // Condenser inlet temperature [C] + Real64 EvapInletTemp = 0.0; // Evaporator inlet temperature [C] + Real64 ActualCOP = 0.0; // Coefficient of performance + Real64 EnergyHeatRecovery = 0.0; // Energy recovered from water-cooled condenser [J] + Real64 HeatRecInletTemp = 0.0; // Heat reclaim inlet temperature [C] + Real64 HeatRecMassFlow = 0.0; // Heat reclaim mass flow rate [kg/s] + int ChillerCondLoopFlowFLoopPLRIndex = 0; // Condenser loop flow rate fraction function of loop PLR + int CondDT = 0; // Temperature difference across condenser + int CondDTScheduleNum = 0; // Temperature difference across condenser schedule index + Real64 MinCondFlowRatio = 0.0; // Minimum condenser flow fraction DataBranchAirLoopPlant::ControlType EquipFlowCtrl = DataBranchAirLoopPlant::ControlType::Invalid; static ReformulatedEIRChillerSpecs *factory(EnergyPlusData &state, std::string const &objectName);