diff --git a/doc/engineering-reference/src/simulation-models-encyclopedic-reference-001/coils.tex b/doc/engineering-reference/src/simulation-models-encyclopedic-reference-001/coils.tex index d0dae116ce9..c4da77a679e 100644 --- a/doc/engineering-reference/src/simulation-models-encyclopedic-reference-001/coils.tex +++ b/doc/engineering-reference/src/simulation-models-encyclopedic-reference-001/coils.tex @@ -1135,7 +1135,7 @@ \subsubsection{Model Description}\label{model-description-2-004} \(\dot{Q}_{cap,crankcase}\) is the crankcase heater capacity (W). -If this cooling coil is used as part of an air-to-air heat pump (Ref. AirLoopHVAC:UnitaryHeat-Pump:AirToAir), the crankcase heater defined for this DX cooling coil is disregarded and the associated output variable is omitted. Instead, the crankcase heater defined for the DX heating coil (Coil:Heating:DX:SingleSpeed) is enabled during the time that the compressor is not running for either heating or cooling. In this instance, RTF in the above equations would be the runtime fraction of the heat pump's heating coil or cooling coil, whichever is greater. +If this cooling coil is used as part of an air-to-air heat pump (e.g., AirLoopHVAC:UnitaryHeatPump:AirToAir, AirLoopHVAC:UnitarySystem, or ZoneHVAC:PackagedTerminalHeatPump), the crankcase heater defined for this DX cooling coil is disregarded and the associated output variable is omitted. Instead, the crankcase heater defined for the DX heating coil (e.g., Coil:Heating:DX:SingleSpeed) is enabled during the time that the compressor is not running for either heating or cooling. In this instance, RTF in the above equations would be the runtime fraction of the heat pump's heating coil or cooling coil, whichever is greater. In addition to calculating the total cooling capacity provided by the DX air conditioner, it is important to properly determine the break down of total cooling capacity into its sensible (temperature) and latent (dehumidification) components. The model computes the sensible/ latent split using the rated SHR and the ADP/BF approach (Carrier et al. 1959). When the DX coil model is initially called during an EnergyPlus simulation, the rated total capacity and rated SHR are used to calculate the coil bypass factor (BF) at rated conditions. The rated total capacity and rated SHR are first used to determine the ratio of change in air humidity ratio to air dry-bulb temperature: @@ -2070,7 +2070,7 @@ \subsubsection{Speed 1 Operation}\label{speed-1-operation} The main reason using the above approach is that outlet conditions are calculated in the same way in low and high speed operation. -The crankcase heater defined for this DX cooling coil is enabled during the time that the compressor is not running for either heating or cooling. The crankcase heater power use from either heating or cooling is reported in the heating coil (Coil:Heating:DX:MultiSpeed). +The crankcase heater defined for this DX cooling coil is enabled during the time that the compressor is not running for either heating or cooling. The crankcase heater power use from either heating or cooling is reported in the heating coil (e.g., Coil:Heating:DX:MultiSpeed). \subsubsection{Higher Speed Operation}\label{higher-speed-operation-000} @@ -3732,7 +3732,7 @@ \subsubsection{Heating Operation}\label{heating-operation-000} \({Q_{cap,crankcase}}\) is the crankcase heater capacity (W). -If this heating coil is used as part of an air-to-air heat pump (Ref. AirLoopHVAC:UnitaryHeat-Pump:AirToAir), the crankcase heater defined for this DX heating coil is enabled during the time that the compressor is not running for either heating or cooling (and the crankcase heater power defined in the DX cooling coil object is disregarded in this case). In this instance, RTF in the above equations would be the runtime fraction of the heat pump's heating coil or cooling coil, whichever is greater. +If this heating coil is used as part of an air-to-air heat pump (e.g., AirLoopHVAC:UnitaryHeatPump:AirToAir, AirLoopHVAC:UnitarySystem, or ZoneHVAC:PackagedTerminalHeatPump), the crankcase heater defined for this DX heating coil is enabled during the time that the compressor is not running for either heating or cooling (and the crankcase heater power defined in the DX cooling coil object is disregarded in this case). In this instance, RTF in the above equations would be the runtime fraction of the heat pump's heating coil or cooling coil, whichever is greater. The properties of the air leaving the heating coil at full-load operation are calculated using the following equations: @@ -4153,7 +4153,7 @@ \subsubsection{Speed 1 Operation}\label{speed-1-operation-1} The main reason for using the above approach is that outlet air conditions are calculated in the same way for all operating speeds. -The crankcase heater defined for this DX heating coil is enabled during the time that the compressor is not running for either heating or cooling. The crankcase heater power use from either heating or cooling is reported in the heating coil. +The crankcase heater defined for this DX heating coil is enabled during the time that the compressor is not running for either heating or cooling. The crankcase heater power use from either heating or cooling is reported in the heating coil (e.g., Coil:Heating:DX:MultiSpeed). \subsubsection{Higher Speed Operation}\label{higher-speed-operation-2} diff --git a/doc/input-output-reference/src/overview/group-coil-cooling-dx.tex b/doc/input-output-reference/src/overview/group-coil-cooling-dx.tex index 9db90bb52c7..626d0b5df06 100644 --- a/doc/input-output-reference/src/overview/group-coil-cooling-dx.tex +++ b/doc/input-output-reference/src/overview/group-coil-cooling-dx.tex @@ -103,7 +103,7 @@ \subsubsection{Inputs}\label{inputs-02} \paragraph{Field: Crankcase Heater Capacity} -This numeric field defines the crankcase heater capacity in Watts. When the outdoor air dry-bulb temperature is below the value specified in the input field Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation (described below), the crankcase heater is enabled during the time that the compressor is not running. If this cooling coil is used as part of an air-to-air heat pump (Ref. AirLoopHVAC:UnitaryHeatPump:AirToAir or PackageTerminal: HeatPump:AirToAir), the crankcase heater defined for this DX cooling coil is ignored and the crankcase heater power defined for the DX heating coil (Ref. Coil:Heating:DX:SingleSpeed) is enabled during the time that the compressor is not running for either heating or cooling. The value for this input field must be greater than or equal to 0, and the default value is 0. To simulate a DX cooling coil without a crankcase heater, enter a value of 0. +This numeric field defines the crankcase heater capacity in Watts. When the outdoor air dry-bulb temperature is below the value specified in the input field Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation (described below), the crankcase heater is enabled during the time that the compressor is not running. If this cooling coil is used as part of an air-to-air heat pump (e.g., AirLoopHVAC:UnitarySystem or ZoneHVAC:PackagedTerminalHeatPump), the crankcase heater defined for this DX cooling coil is ignored and the crankcase heater power defined for the DX heating coil (e.g., Coil:Heating:DX:SingleSpeed) is enabled during the time that the compressor is not running for either heating or cooling. The value for this input field must be greater than or equal to 0, and the default value is 0. To simulate a DX cooling coil without a crankcase heater, enter a value of 0. \paragraph{Field: Crankcase Heater Capacity Function of Temperature Curve Name} @@ -681,8 +681,16 @@ \subsubsection{Outputs}\label{outputs-01} \item HVAC, Average, Cooling Coil Rate {[}W{]} \item HVAC, Sum, Cooling Coil Energy {[}J{]} \item HVAC, Average, Cooling Coil Runtime Fraction {[]} +\end{itemize} + +If not part of a heat pump (if part of a heat pump, crankcase heater is reported only for the heating coil): + +\begin{itemize} \item HVAC, Average, Cooling Coil Crankcase Heater Electricity Rate {[}W{]} \item HVAC, Sum, Cooling Coil Crankcase Heater Electricity Energy {[}J{]} +\end{itemize} + +\begin{itemize} \item HVAC, Average, Cooling Coil Air Mass Flow Rate {[}kg/s{]} \item HVAC, Average, Cooling Coil Air Inlet Temperature {[}C{]} \item HVAC, Average, Cooling Coil Air Inlet Humidity Ratio {[}kgWater/kgDryAir{]} diff --git a/doc/input-output-reference/src/overview/group-heating-and-cooling-coils.tex b/doc/input-output-reference/src/overview/group-heating-and-cooling-coils.tex index 261cc4ed13c..f49bb215813 100644 --- a/doc/input-output-reference/src/overview/group-heating-and-cooling-coils.tex +++ b/doc/input-output-reference/src/overview/group-heating-and-cooling-coils.tex @@ -2178,7 +2178,7 @@ \subsubsection{Inputs}\label{inputs-13-004} \paragraph{Field: Crankcase Heater Capacity}\label{field-crankcase-heater-capacity} -This numeric field defines the crankcase heater capacity in Watts. When the outdoor air dry-bulb temperature is below the value specified in the input field Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation (described below), the crankcase heater is enabled during the time that the compressor is not running. If this cooling coil is used as part of an air-to-air heat pump (Ref. \hyperref[airloophvacunitaryheatpumpairtoair]{AirLoopHVAC:UnitaryHeatPump:AirToAir} or PackageTerminal: HeatPump:AirToAir), the crankcase heater defined for this DX cooling coil is ignored and the crankcase heater power defined for the DX heating coil (Ref. \hyperref[coilheatingdxsinglespeed]{Coil:Heating:DX:SingleSpeed}) is enabled during the time that the compressor is not running for either heating or cooling. The value for this input field must be greater than or equal to 0, and the default value is 0. To simulate a DX cooling coil without a crankcase heater, enter a value of 0. +This numeric field defines the crankcase heater capacity in Watts. When the outdoor air dry-bulb temperature is below the value specified in the input field Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation (described below), the crankcase heater is enabled during the time that the compressor is not running. If this cooling coil is used as part of an air-to-air heat pump (e.g., AirLoopHVAC:UnitaryHeatPump:AirToAir, AirLoopHVAC:UnitarySystem, or ZoneHVAC:PackagedTerminalHeatPump), the crankcase heater defined for this DX cooling coil is ignored and the crankcase heater power defined for the DX heating coil (e.g., Coil:Heating:DX:SingleSpeed) is enabled during the time that the compressor is not running for either heating or cooling. The value for this input field must be greater than or equal to 0, and the default value is 0. To simulate a DX cooling coil without a crankcase heater, enter a value of 0. \paragraph{Field: Crankcase Heater Capacity Function of Temperature Curve Name} @@ -2628,7 +2628,7 @@ \subsubsection{Inputs}\label{inputs-15-004} \paragraph{Field: Crankcase Heater Capacity}\label{field-crankcase-heater-capacity-1} -This numeric field defines the crankcase heater capacity in Watts. When the outdoor air dry-bulb temperature is below the value specified in the input field Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation (described below), the crankcase heater is enabled during the time that the compressor is not running. If this cooling coil is used as part of an air-to-air heat pump (Ref. \hyperref[airloophvacunitarysystem]{AirLoopHVAC:UnitarySystem} and \hyperref[airloophvacunitaryheatcoolvavchangeoverbypass]{AirLoopHVAC:UnitaryHeatCool:VAVChangeoverBypass}), the crankcase heater defined for this DX cooling coil is ignored and the crankcase heater power defined for the DX heating coil (Ref. \hyperref[coilheatingdxsinglespeed]{Coil:Heating:DX:SingleSpeed}) is enabled during the time that the compressor is not running for either heating or cooling. The value for this input field must be greater than or equal to 0, and the default value is 0. To simulate a DX cooling coil without a crankcase heater, enter a value of 0. +This numeric field defines the crankcase heater capacity in Watts. When the outdoor air dry-bulb temperature is below the value specified in the input field Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation (described below), the crankcase heater is enabled during the time that the compressor is not running. If this cooling coil is used as part of an air-to-air heat pump (e.g., AirLoopHVAC:UnitarySystem or AirLoopHVAC:UnitaryHeatCool:VAVChangeoverBypass), the crankcase heater defined for this DX cooling coil is ignored and the crankcase heater power defined for the DX heating coil (e.g., Coil:Heating:DX:SingleSpeed) is enabled during the time that the compressor is not running for either heating or cooling. The value for this input field must be greater than or equal to 0, and the default value is 0. To simulate a DX cooling coil without a crankcase heater, enter a value of 0. \paragraph{Field: Crankcase Heater Capacity Function of Temperature Curve Name} @@ -2774,7 +2774,7 @@ \subsubsection{Inputs}\label{inputs-16-003} \paragraph{Field: Crankcase Heater Capacity}\label{field-crankcase-heater-capacity-2} -This numeric field defines the crankcase heater capacity in Watts. When the outdoor air dry-bulb temperature is below the value specified in the input field Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation (described below), the crankcase heater is enabled during the time that the compressor is not running. The value for this input field must be greater than or equal to 0. If this input field is left blank, the default value is 0. To simulate a unit without a crankcase heater, enter a value of 0. +This numeric field defines the crankcase heater capacity in Watts. When the outdoor air dry-bulb temperature is below the value specified in the input field Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation (described below), the crankcase heater is enabled during the time that the compressor is not running. If this cooling coil is used as part of an air-to-air heat pump (e.g., AirLoopHVAC:UnitarySystem), the crankcase heater defined for this DX cooling coil is ignored and the crankcase heater power defined for the DX heating coil (e.g., Coil:Heating:DX:SingleSpeed) is enabled during the time that the compressor is not running for either heating or cooling. The value for this input field must be greater than or equal to 0, and the default value is 0. To simulate a DX cooling coil without a crankcase heater, enter a value of 0. \paragraph{Field: Crankcase Heater Capacity Function of Temperature Curve Name} @@ -3072,7 +3072,7 @@ \subsubsection{Outputs}\label{outputs-12-002} HVAC,Average,Cooling Coil Runtime Fraction {[]} \end{itemize} -If not part of AirLoopHVAC:UnitaryHeatPump:AirToAir (if part of a heat pump, crankcase heater is reported only for the heating coil): +If not part of a heat pump (if part of a heat pump, crankcase heater is reported only for the heating coil): \begin{itemize} \item @@ -3350,7 +3350,7 @@ \subsubsection{Inputs}\label{inputs-17-001} \paragraph{Field: Crankcase Heater Capacity}\label{field-crankcase-heater-capacity-3} -This numeric field defines the crankcase heater capacity in Watts. When the outdoor air drybulb temperature is below the value specified in the input field Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation (described below), the crankcase heater is enabled during the time that the compressor is not running. If this cooling coil is used as part of an air-to-air heat pump, the crankcase heater defined for this DX cooling coil is ignored and the crankcase heater power defined for the DX heating coil (Ref. \hyperref[coilheatingdxsinglespeed]{Coil:Heating:DX:SingleSpeed}) is enabled during the time that the compressor is not running for either heating or cooling. The value for this input field must be greater than or equal to 0, and the default value is 0. To simulate a DX cooling coil without a crankcase heater, enter a value of 0. +This numeric field defines the crankcase heater capacity in Watts. When the outdoor air dry-bulb temperature is below the value specified in the input field Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation (described below), the crankcase heater is enabled during the time that the compressor is not running. If this cooling coil is used as part of an air-to-air heat pump (e.g., AirLoopHVAC:UnitaryHeatPump:AirToAir, AirLoopHVAC:UnitarySystem, or ZoneHVAC:PackagedTerminalHeatPump), the crankcase heater defined for this DX cooling coil is ignored and the crankcase heater power defined for the DX heating coil (e.g., Coil:Heating:DX:SingleSpeed) is enabled during the time that the compressor is not running for either heating or cooling. The value for this input field must be greater than or equal to 0, and the default value is 0. To simulate a DX cooling coil without a crankcase heater, enter a value of 0. \paragraph{Field: Crankcase Heater Capacity Function of Temperature Curve Name} @@ -3617,10 +3617,18 @@ \subsubsection{Outputs}\label{outputs-13-001} HVAC,Sum,Cooling Coil Latent Cooling Energy {[}J{]} \item HVAC,Sum,Cooling Coil Source Side Heat Transfer Energy {[}J{]} +\end{itemize} + +If not part of a heat pump (if part of a heat pump, crankcase heater is reported only for the heating coil): + +\begin{itemize} \item HVAC,Average,Cooling Coil Crankcase Heater Electricity Rate {[}W{]} \item HVAC,Sum,Cooling Coil Crankcase Heater Electricity Energy {[}J{]} +\end{itemize} + +\begin{itemize} \item HVAC,Average,Cooling Coil Condensate Volume Flow Rate {[}m3/s{]} \item @@ -4168,7 +4176,7 @@ \subsubsection{Inputs}\label{inputs-19-001} \paragraph{Field: Crankcase Heater Capacity}\label{field-crankcase-heater-capacity-4} -This numeric field defines the crankcase heater capacity in Watts. When the outdoor air dry-bulb temperature is below the value specified in the input field Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation (described below), the crankcase heater is enabled during the time that the compressor is not running. If this heating coil is used as part of an air-to-air heat pump (Ref. \hyperref[airloophvacunitaryheatpumpairtoair]{AirLoopHVAC:UnitaryHeatPump:AirToAir} or \hyperref[zonehvacpackagedterminalheatpump]{ZoneHVAC:PackagedTerminalHeatPump}), the crankcase heater defined for this DX heating coil is enabled during the time that the compressor is not running for either heating or cooling (and the crankcase heater power defined in the DX cooling coil object is disregarded in this case). The value for this input field must be greater than or equal to 0. If this input field is left blank, the default value is 0. To simulate a unit without a crankcase heater, enter a value of 0. +This numeric field defines the crankcase heater capacity in Watts. When the outdoor air dry-bulb temperature is below the value specified in the input field Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation (described below), the crankcase heater is enabled during the time that the compressor is not running. If this heating coil is used as part of an air-to-air heat pump (e.g., AirLoopHVAC:UnitaryHeatPump:AirToAir, AirLoopHVAC:UnitarySystem, or ZoneHVAC:PackagedTerminalHeatPump), the crankcase heater defined for this DX heating coil is enabled during the time that the compressor is not running for either heating or cooling (and the crankcase heater power defined in the DX cooling coil object is disregarded in this case). The value for this input field must be greater than or equal to 0. If this input field is left blank, the default value is 0. To simulate a unit without a crankcase heater, enter a value of 0. \paragraph{Field: Crankcase Heater Capacity Function of Temperature Curve Name} @@ -4374,7 +4382,7 @@ \subsubsection{Inputs}\label{inputs-20-001} \paragraph{Field: Crankcase Heater Capacity}\label{field-crankcase-heater-capacity-5} -This numeric field defines the crankcase heater capacity in Watts. When the outdoor air dry-bulb temperature is below the value specified in the input field Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation (described below), the crankcase heater is enabled during the time that the compressor is not running. The value for this input field must be greater than or equal to 0. If this input field is left blank, the default value is 0. To simulate a unit without a crankcase heater, enter a value of 0. +This numeric field defines the crankcase heater capacity in Watts. When the outdoor air dry-bulb temperature is below the value specified in the input field Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation (described below), the crankcase heater is enabled during the time that the compressor is not running. If this heating coil is used as part of an air-to-air heat pump (e.g., AirLoopHVAC:UnitarySystem), the crankcase heater defined for this DX heating coil is enabled during the time that the compressor is not running for either heating or cooling (and the crankcase heater power defined in the DX cooling coil object is disregarded in this case). The value for this input field must be greater than or equal to 0. If this input field is left blank, the default value is 0. To simulate a unit without a crankcase heater, enter a value of 0. \paragraph{Field: Crankcase Heater Capacity Function of Temperature Curve Name} @@ -4769,7 +4777,7 @@ \subsubsection{Inputs}\label{inputs-21-001} \paragraph{Field: Crankcase Heater Capacity}\label{field-crankcase-heater-capacity-6} -This numeric field defines the crankcase heater capacity in Watts. When the outdoor air drybulb temperature is below the value specified in the input field Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation (described below), the crankcase heater is enabled during the time that the compressor is not running. The value for this input field must be greater than or equal to 0. If this input field is left blank, the default value is 0. To simulate a unit without a crankcase heater, enter a value of 0. +This numeric field defines the crankcase heater capacity in Watts. When the outdoor air dry-bulb temperature is below the value specified in the input field Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation (described below), the crankcase heater is enabled during the time that the compressor is not running. If this heating coil is used as part of an air-to-air heat pump (e.g., AirLoopHVAC:UnitaryHeatPump:AirToAir, AirLoopHVAC:UnitarySystem, or ZoneHVAC:PackagedTerminalHeatPump), the crankcase heater defined for this DX heating coil is enabled during the time that the compressor is not running for either heating or cooling (and the crankcase heater power defined in the DX cooling coil object is disregarded in this case). The value for this input field must be greater than or equal to 0. If this input field is left blank, the default value is 0. To simulate a unit without a crankcase heater, enter a value of 0. \paragraph{Field: Crankcase Heater Capacity Function of Temperature Curve Name} diff --git a/src/EnergyPlus/Coils/CoilCoolingDX.cc b/src/EnergyPlus/Coils/CoilCoolingDX.cc index 4a4a1233253..df2085225f2 100644 --- a/src/EnergyPlus/Coils/CoilCoolingDX.cc +++ b/src/EnergyPlus/Coils/CoilCoolingDX.cc @@ -348,23 +348,25 @@ void CoilCoolingDX::oneTimeInit(EnergyPlusData &state) OutputProcessor::TimeStepType::System, OutputProcessor::StoreType::Average, this->name); - SetupOutputVariable(state, - "Cooling Coil Crankcase Heater Electricity Rate", - Constant::Units::W, - this->performance->crankcaseHeaterPower, - OutputProcessor::TimeStepType::System, - OutputProcessor::StoreType::Average, - this->name); - SetupOutputVariable(state, - "Cooling Coil Crankcase Heater Electricity Energy", - Constant::Units::J, - this->performance->crankcaseHeaterElectricityConsumption, - OutputProcessor::TimeStepType::System, - OutputProcessor::StoreType::Sum, - this->name, - Constant::eResource::Electricity, - OutputProcessor::Group::HVAC, - OutputProcessor::EndUseCat::Cooling); + if (this->performance->ReportCoolingCoilCrankcasePower) { + SetupOutputVariable(state, + "Cooling Coil Crankcase Heater Electricity Rate", + Constant::Units::W, + this->performance->crankcaseHeaterPower, + OutputProcessor::TimeStepType::System, + OutputProcessor::StoreType::Average, + this->name); + SetupOutputVariable(state, + "Cooling Coil Crankcase Heater Electricity Energy", + Constant::Units::J, + this->performance->crankcaseHeaterElectricityConsumption, + OutputProcessor::TimeStepType::System, + OutputProcessor::StoreType::Sum, + this->name, + Constant::eResource::Electricity, + OutputProcessor::Group::HVAC, + OutputProcessor::EndUseCat::Cooling); + } // Ported from variable speed coil SetupOutputVariable(state, "Cooling Coil Air Mass Flow Rate", diff --git a/src/EnergyPlus/Coils/CoilCoolingDXPerformanceBase.hh b/src/EnergyPlus/Coils/CoilCoolingDXPerformanceBase.hh index 1e748774223..06e248cbfa6 100644 --- a/src/EnergyPlus/Coils/CoilCoolingDXPerformanceBase.hh +++ b/src/EnergyPlus/Coils/CoilCoolingDXPerformanceBase.hh @@ -85,6 +85,7 @@ struct CoilCoolingDXPerformanceBase Real64 wasteHeatRate = 0.0; Real64 recoveredEnergyRate = 0.0; + bool ReportCoolingCoilCrankcasePower = true; // logical determines if the cooling coil crankcase heater power is reported Real64 crankcaseHeaterCap = 0.0; Real64 crankcaseHeaterPower = 0.0; int crankcaseHeaterCapacityCurveIndex = 0; diff --git a/src/EnergyPlus/DXCoils.cc b/src/EnergyPlus/DXCoils.cc index 49a3ed40853..cb208523cdb 100644 --- a/src/EnergyPlus/DXCoils.cc +++ b/src/EnergyPlus/DXCoils.cc @@ -15959,7 +15959,6 @@ int GetHPCoolingCoilIndex(EnergyPlusData &state, DataLoopNode::ConnectionObjectType CompSetsParentType; // Parent object type which uses DX heating coil pass into this function std::string CompSetsParentName; for (WhichComp = 1; WhichComp <= state.dataBranchNodeConnections->NumCompSets; ++WhichComp) { - if (HeatingCoilTypeNum != state.dataBranchNodeConnections->CompSets(WhichComp).ComponentObjectType || !Util::SameString(HeatingCoilName, state.dataBranchNodeConnections->CompSets(WhichComp).CName)) { continue; @@ -16019,7 +16018,7 @@ int GetHPCoolingCoilIndex(EnergyPlusData &state, } else { // ErrorFound, Coil:Heating:DX:SingleSpeed is used in wrong type of parent object (should never get here) ShowSevereError(state, - EnergyPlus::format("Configuration error in {}\"{}\"", + EnergyPlus::format("Configuration error in {} \"{}\"", BranchNodeConnections::ConnectionObjectTypeNames[static_cast(CompSetsParentType)], CompSetsParentName)); ShowContinueError(state, "DX heating coil not allowed in this configuration."); @@ -16036,7 +16035,7 @@ int GetHPCoolingCoilIndex(EnergyPlusData &state, if (thisDXCoolingCoil.CrankcaseHeaterCapacity != thisDXHeatingCoil.CrankcaseHeaterCapacity || thisDXCoolingCoil.MaxOATCrankcaseHeater != thisDXHeatingCoil.MaxOATCrankcaseHeater) { ShowWarningError(state, "Crankcase heater capacity or max outdoor temp for crankcase heater operation specified in"); - ShowContinueError(state, EnergyPlus::format("Coil:Cooling:DX:SingleSpeed = {}", thisDXCoolingCoil.Name)); + ShowContinueError(state, EnergyPlus::format("{} = {}", thisDXCoolingCoil.DXCoilType, thisDXCoolingCoil.Name)); ShowContinueError(state, EnergyPlus::format("is different than that specified in Coil:Heating:DX:SingleSpeed = {}.", HeatingCoilName)); ShowContinueError(state, diff --git a/src/EnergyPlus/HVACDXHeatPumpSystem.cc b/src/EnergyPlus/HVACDXHeatPumpSystem.cc index c9fe845f307..a0894d4d4d5 100644 --- a/src/EnergyPlus/HVACDXHeatPumpSystem.cc +++ b/src/EnergyPlus/HVACDXHeatPumpSystem.cc @@ -252,7 +252,6 @@ namespace HVACDXHeatPumpSystem { using BranchNodeConnections::TestCompSet; using DXCoils::GetCoilInletNode; using DXCoils::GetCoilOutletNode; - using DXCoils::SetCoilSystemHeatingDXFlag; using VariableSpeedCoils::GetCoilInletNodeVariableSpeed; using VariableSpeedCoils::GetCoilOutletNodeVariableSpeed; @@ -393,7 +392,11 @@ namespace HVACDXHeatPumpSystem { DXHeatPumpSystem(DXHeatSysNum).fanOp = HVAC::FanOp::Continuous; if (DXHeatPumpSystem(DXHeatSysNum).HeatPumpCoilType_Num != HVAC::Coil_HeatingAirToAirVariableSpeed) { - SetCoilSystemHeatingDXFlag(state, DXHeatPumpSystem(DXHeatSysNum).HeatPumpCoilType, DXHeatPumpSystem(DXHeatSysNum).HeatPumpCoilName); + DXCoils::SetCoilSystemHeatingDXFlag( + state, DXHeatPumpSystem(DXHeatSysNum).HeatPumpCoilType, DXHeatPumpSystem(DXHeatSysNum).HeatPumpCoilName); + } else { + VariableSpeedCoils::SetCoilSystemHeatingDXFlag( + state, DXHeatPumpSystem(DXHeatSysNum).HeatPumpCoilType, DXHeatPumpSystem(DXHeatSysNum).HeatPumpCoilName); } } // End of the DX System Loop diff --git a/src/EnergyPlus/IntegratedHeatPump.cc b/src/EnergyPlus/IntegratedHeatPump.cc index e8cbf31a4f8..cfdc26c033f 100644 --- a/src/EnergyPlus/IntegratedHeatPump.cc +++ b/src/EnergyPlus/IntegratedHeatPump.cc @@ -1078,6 +1078,9 @@ void GetIHPInput(EnergyPlusData &state) ihp.MaxHeatAirVolFlow = 1e10; ihp.MaxCoolAirMassFlow = 1e10; ihp.MaxCoolAirVolFlow = 1e10; + + VariableSpeedCoils::SetCoilSystemHeatingDXFlag(state, ihp.SHCoilType, ihp.SHCoilName); + VariableSpeedCoils::SetCoilSystemHeatingDXFlag(state, ihp.SHDWHHeatCoilType, ihp.SHDWHHeatCoilName); } if (ErrorsFound) { diff --git a/src/EnergyPlus/UnitarySystem.cc b/src/EnergyPlus/UnitarySystem.cc index 33a4a5631d6..036601cb43e 100644 --- a/src/EnergyPlus/UnitarySystem.cc +++ b/src/EnergyPlus/UnitarySystem.cc @@ -4844,6 +4844,7 @@ namespace UnitarySystems { this->m_HeatingCoilType_Num == HVAC::CoilDX_MultiSpeedHeating || this->m_HeatingCoilType_Num == HVAC::CoilDX_HeatingEmpirical) { this->m_HeatPump = true; + // FIXME: ReportCoolingCoilCrankcasePower already handled in DXCoils.cc? } } @@ -4924,6 +4925,12 @@ namespace UnitarySystems { this->m_HeatingCoilType_Num == HVAC::CoilDX_MultiSpeedHeating || this->m_HeatingCoilType_Num == HVAC::CoilDX_HeatingEmpirical) { this->m_HeatPump = true; + if (this->m_HeatingCoilType_Num == HVAC::Coil_HeatingAirToAirVariableSpeed || + this->m_HeatingCoilType_Num == HVAC::CoilDX_MultiSpeedHeating || + this->m_HeatingCoilType_Num == HVAC::CoilDX_HeatingEmpirical) { + auto &newCoil = state.dataCoilCoolingDX->coilCoolingDXs[this->m_CoolingCoilIndex]; + newCoil.performance->ReportCoolingCoilCrankcasePower = false; + } } } } @@ -4969,6 +4976,7 @@ namespace UnitarySystems { this->m_HeatingCoilType_Num == HVAC::CoilDX_MultiSpeedHeating || this->m_HeatingCoilType_Num == HVAC::CoilDX_HeatingEmpirical) { this->m_HeatPump = true; + // FIXME: ReportCoolingCoilCrankcasePower already handled in DXCoils.cc? } } } @@ -5247,6 +5255,7 @@ namespace UnitarySystems { this->m_HeatingCoilType_Num == HVAC::CoilDX_MultiSpeedHeating || this->m_HeatingCoilType_Num == HVAC::CoilDX_HeatingEmpirical) { this->m_HeatPump = true; + // FIXME: ReportCoolingCoilCrankcasePower already handled in VariableSpeedCoils.cc? } } @@ -5285,6 +5294,7 @@ namespace UnitarySystems { this->m_HeatingCoilType_Num == HVAC::CoilDX_MultiSpeedHeating || this->m_HeatingCoilType_Num == HVAC::CoilDX_HeatingEmpirical) { this->m_HeatPump = true; + // FIXME: ReportCoolingCoilCrankcasePower already handled in DXCoils.cc? } } diff --git a/src/EnergyPlus/VariableSpeedCoils.cc b/src/EnergyPlus/VariableSpeedCoils.cc index 11ad3f8ab0f..b2779226b61 100644 --- a/src/EnergyPlus/VariableSpeedCoils.cc +++ b/src/EnergyPlus/VariableSpeedCoils.cc @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -2760,24 +2761,6 @@ namespace VariableSpeedCoils { OutputProcessor::EndUseCat::Cooling); } } - - SetupOutputVariable(state, - "Cooling Coil Crankcase Heater Electricity Rate", - Constant::Units::W, - varSpeedCoil.CrankcaseHeaterPower, - OutputProcessor::TimeStepType::System, - OutputProcessor::StoreType::Average, - varSpeedCoil.Name); - SetupOutputVariable(state, - "Cooling Coil Crankcase Heater Electricity Energy", - Constant::Units::J, - varSpeedCoil.CrankcaseHeaterConsumption, - OutputProcessor::TimeStepType::System, - OutputProcessor::StoreType::Sum, - varSpeedCoil.Name, - Constant::eResource::Electricity, - OutputProcessor::Group::HVAC, - OutputProcessor::EndUseCat::Cooling); } else { // air source heating coils SetupOutputVariable(state, @@ -3450,6 +3433,55 @@ namespace VariableSpeedCoils { state.dataVariableSpeedCoils->MyPlantScanFlag(DXCoilNum) = false; } + // Find the companion upstream coil (DX cooling coil) that is used with DX heating coils (HP AC units only) + if (varSpeedCoil.FindCompanionUpStreamCoil) { + if (varSpeedCoil.VSCoilType == HVAC::Coil_HeatingAirToAirVariableSpeed) { + varSpeedCoil.CompanionUpstreamDXCoil = GetHPCoolingCoilIndex(state, varSpeedCoil.VarSpeedCoilType, varSpeedCoil.Name, DXCoilNum); + if (varSpeedCoil.CompanionUpstreamDXCoil > 0) { + state.dataVariableSpeedCoils->VarSpeedCoil(varSpeedCoil.CompanionUpstreamDXCoil).ReportCoolingCoilCrankcasePower = false; + varSpeedCoil.FindCompanionUpStreamCoil = false; + } else { + varSpeedCoil.FindCompanionUpStreamCoil = false; + } + } else { + varSpeedCoil.FindCompanionUpStreamCoil = false; + } + } + + // CR7308 - Wait for zone and air loop equipment to be simulated, then print out report variables + if (state.dataVariableSpeedCoils->CrankcaseHeaterReportVarFlag) { + if (state.dataAirLoop->AirLoopInputsFilled) { + // Set report variables for DX cooling coils that will have a crankcase heater (all DX coils not used in a HP AC unit) + int DXCoilNumTemp; // Counter for crankcase heater report variable DO loop + for (DXCoilNumTemp = 1; DXCoilNumTemp <= state.dataVariableSpeedCoils->NumVarSpeedCoils; ++DXCoilNumTemp) { + auto &dXCoil_withCrankCase = state.dataVariableSpeedCoils->VarSpeedCoil(DXCoilNumTemp); + if (dXCoil_withCrankCase.VSCoilType == HVAC::Coil_CoolingAirToAirVariableSpeed) { + if (dXCoil_withCrankCase.ReportCoolingCoilCrankcasePower) { + SetupOutputVariable(state, + "Cooling Coil Crankcase Heater Electricity Rate", + Constant::Units::W, + dXCoil_withCrankCase.CrankcaseHeaterPower, + OutputProcessor::TimeStepType::System, + OutputProcessor::StoreType::Average, + dXCoil_withCrankCase.Name); + SetupOutputVariable(state, + "Cooling Coil Crankcase Heater Electricity Energy", + Constant::Units::J, + dXCoil_withCrankCase.CrankcaseHeaterConsumption, + OutputProcessor::TimeStepType::System, + OutputProcessor::StoreType::Sum, + dXCoil_withCrankCase.Name, + Constant::eResource::Electricity, + OutputProcessor::Group::HVAC, + OutputProcessor::EndUseCat::Cooling); + dXCoil_withCrankCase.ReportCoolingCoilCrankcasePower = false; + } + } + } + state.dataVariableSpeedCoils->CrankcaseHeaterReportVarFlag = false; + } //(AirLoopInputsFilled)THEN + } //(CrankcaseHeaterReportVarFlag)THEN + if (!state.dataGlobal->SysSizingCalc && state.dataVariableSpeedCoils->MySizeFlag(DXCoilNum) && !state.dataVariableSpeedCoils->MyPlantScanFlag(DXCoilNum)) { // for each furnace, do the sizing once. @@ -7311,6 +7343,128 @@ namespace VariableSpeedCoils { return state.dataVariableSpeedCoils->VarSpeedCoil(CoilIndex).MinOATCompressor; } + int GetHPCoolingCoilIndex(EnergyPlusData &state, + std::string const &HeatingCoilType, // Type of DX heating coil used in HP + std::string const &HeatingCoilName, // Name of DX heating coil used in HP + int const HeatingCoilIndex // Index of DX heating coil used in HP + ) + { + + // FUNCTION INFORMATION: + // AUTHOR J. Robertson + // DATE WRITTEN March 2026 + + // PURPOSE OF THIS FUNCTION: + // A modified copy of DXCoils::GetHPCoolingCoilIndex. + // This function looks up the given DX heating coil and returns the companion DX cooling coil. + + // Return value + int DXCoolingCoilIndex; // Index of HP DX cooling coil returned from this function + + // FUNCTION LOCAL VARIABLE DECLARATIONS: + int WhichComp; // DO loop counter to find correct comp set + int WhichCompanionComp; // DO loop counter to find companion coil comp set + + DXCoolingCoilIndex = 0; + + DataLoopNode::ConnectionObjectType HeatingCoilTypeNum = static_cast( + getEnumValue(BranchNodeConnections::ConnectionObjectTypeNamesUC, Util::makeUPPER(HeatingCoilType))); + + DataLoopNode::ConnectionObjectType CompSetsParentType; // Parent object type which uses DX heating coil pass into this function + std::string CompSetsParentName; + for (WhichComp = 1; WhichComp <= state.dataBranchNodeConnections->NumCompSets; ++WhichComp) { + if (HeatingCoilTypeNum != state.dataBranchNodeConnections->CompSets(WhichComp).ComponentObjectType || + !Util::SameString(HeatingCoilName, state.dataBranchNodeConnections->CompSets(WhichComp).CName)) { + continue; + } + CompSetsParentType = state.dataBranchNodeConnections->CompSets(WhichComp).ParentObjectType; + CompSetsParentName = state.dataBranchNodeConnections->CompSets(WhichComp).ParentCName; + if ((CompSetsParentType == DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpAirToAir) || + (CompSetsParentType == DataLoopNode::ConnectionObjectType::ZoneHVACPackagedTerminalHeatPump) || + (CompSetsParentType == DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed) || + (CompSetsParentType == DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatCoolVAVChangeoverBypass) || + (CompSetsParentType == DataLoopNode::ConnectionObjectType::AirLoopHVACUnitarySystem)) { + // Search for DX cooling coils + for (WhichCompanionComp = 1; WhichCompanionComp <= state.dataBranchNodeConnections->NumCompSets; ++WhichCompanionComp) { + if (!Util::SameString(state.dataBranchNodeConnections->CompSets(WhichCompanionComp).ParentCName, CompSetsParentName) || + (state.dataBranchNodeConnections->CompSets(WhichCompanionComp).ComponentObjectType != + DataLoopNode::ConnectionObjectType::CoilCoolingDXVariableSpeed)) { + continue; + } + DXCoolingCoilIndex = Util::FindItemInList(state.dataBranchNodeConnections->CompSets(WhichCompanionComp).CName, + state.dataVariableSpeedCoils->VarSpeedCoil); + break; + } + } else { + // ErrorFound, Coil:Heating:DX:VariableSpeed is used in wrong type of parent object (should never get here) + ShowSevereError(state, + EnergyPlus::format("Configuration error in {} \"{}\"", + BranchNodeConnections::ConnectionObjectTypeNames[static_cast(CompSetsParentType)], + CompSetsParentName)); + ShowContinueError(state, "DX heating coil not allowed in this configuration."); + ShowFatalError(state, "Preceding condition(s) causes termination."); + } + break; + } + + // Check and warn user is crankcase heater power or max OAT for crankcase heater differs in DX cooling and heating coils + if (DXCoolingCoilIndex > 0) { + auto &thisDXCoolingCoil = state.dataVariableSpeedCoils->VarSpeedCoil(DXCoolingCoilIndex); + auto &thisDXHeatingCoil = state.dataVariableSpeedCoils->VarSpeedCoil(HeatingCoilIndex); + if (thisDXCoolingCoil.CrankcaseHeaterCapacity != 0.0) { + if (thisDXCoolingCoil.CrankcaseHeaterCapacity != thisDXHeatingCoil.CrankcaseHeaterCapacity || + thisDXCoolingCoil.MaxOATCrankcaseHeater != thisDXHeatingCoil.MaxOATCrankcaseHeater) { + ShowWarningError(state, "Crankcase heater capacity or max outdoor temp for crankcase heater operation specified in"); + ShowContinueError(state, EnergyPlus::format("{} = {}", thisDXCoolingCoil.VarSpeedCoilType, thisDXCoolingCoil.Name)); + ShowContinueError(state, + EnergyPlus::format("is different than that specified in Coil:Heating:DX:SingleSpeed = {}.", HeatingCoilName)); + ShowContinueError(state, + EnergyPlus::format("Both of these DX coils are part of {}={}.", + BranchNodeConnections::ConnectionObjectTypeNames[static_cast(CompSetsParentType)], + CompSetsParentName)); + ShowContinueError(state, "The value specified in the DX heating coil will be used and the simulation continues..."); + } + } + } + + return DXCoolingCoilIndex; + } + + void SetCoilSystemHeatingDXFlag(EnergyPlusData &state, + std::string const &CoilType, // must match coil types in this module + std::string const &CoilName // must match coil names for the coil type + ) + { + + // SUBROUTINE INFORMATION: + // AUTHOR J. Robertson + // DATE WRITTEN March 2026 + + // PURPOSE OF THIS SUBROUTINE: + // A modified copy of DXCoils::SetCoilSystemHeatingDXFlag. + // inform DX heating coil that is is part of a CoilSystem:Heating:DX + // and therefore it need not find its companion cooling coil + + // METHODOLOGY EMPLOYED: + // set value of logical flag FindCompanionUpStreamCoil to true + + // SUBROUTINE LOCAL VARIABLE DECLARATIONS: + int WhichCoil; + + // Obtains and Allocates DXCoils + if (state.dataVariableSpeedCoils->GetCoilsInputFlag) { + GetVarSpeedCoilInput(state); + state.dataVariableSpeedCoils->GetCoilsInputFlag = false; + } + + WhichCoil = Util::FindItemInList(CoilName, state.dataVariableSpeedCoils->VarSpeedCoil); + if (WhichCoil != 0) { + state.dataVariableSpeedCoils->VarSpeedCoil(WhichCoil).FindCompanionUpStreamCoil = false; + } else { + ShowSevereError(state, EnergyPlus::format("SetCoilSystemHeatingDXFlag: Could not find Coil, Type=\"{}\"Name=\"{}\"", CoilType, CoilName)); + } + } + int GetVSCoilNumOfSpeeds(EnergyPlusData &state, std::string const &CoilName, // must match coil names for the coil type bool &ErrorsFound // set to true if problem diff --git a/src/EnergyPlus/VariableSpeedCoils.hh b/src/EnergyPlus/VariableSpeedCoils.hh index c369accbf13..9f0eb74fe09 100644 --- a/src/EnergyPlus/VariableSpeedCoils.hh +++ b/src/EnergyPlus/VariableSpeedCoils.hh @@ -143,6 +143,9 @@ namespace VariableSpeedCoils { Real64 FrostHeatingCapacityMultiplierEMSOverrideValue; // value to use for EMS override bool FrostHeatingInputPowerMultiplierEMSOverrideOn; // if true, then EMS is calling to override multiplier for power when system is in defrost Real64 FrostHeatingInputPowerMultiplierEMSOverrideValue; // value to use for EMS override + int CompanionUpstreamDXCoil; // index number of the DX coil that is "upstream" of this DX coil. Currently used for + // UnitarySystem:HeatPump:AirToAir for proper calculation of crankcase heater energy + // consumption // set by parent object and "pushed" to this structure in SetVSWSHPData subroutine bool FindCompanionUpStreamCoil; // Flag to get the companion coil in Init bool IsDXCoilInZone; // true means dx coil is in zone instead of outside @@ -460,6 +463,17 @@ namespace VariableSpeedCoils { bool &ErrorsFound // set to true if problem ); + void SetCoilSystemHeatingDXFlag(EnergyPlusData &state, + std::string const &CoilType, // must match coil types in this module + std::string const &CoilName // must match coil names for the coil type + ); + + int GetHPCoolingCoilIndex(EnergyPlusData &state, + std::string const &HeatingCoilType, // Type of DX heating coil used in HP + std::string const &HeatingCoilName, // Name of DX heating coil used in HP + int const HeatingCoilIndex // Index of DX heating coil used in HP + ); + int GetVSCoilNumOfSpeeds(EnergyPlusData &state, std::string const &CoilName, // must match coil names for the coil type bool &ErrorsFound // set to true if problem @@ -540,6 +554,7 @@ struct VariableSpeedCoilsData : BaseGlobalStruct bool MyOneTimeFlag = true; // one time allocation flag bool GetCoilsInputFlag = true; // Flag set to make sure you get input once // LOGICAL, ALLOCATABLE, DIMENSION(:) :: MySizeFlag + bool CrankcaseHeaterReportVarFlag = true; Real64 SourceSideMassFlowRate = 0.0; // Source Side Mass flow rate [Kg/s] Real64 SourceSideInletTemp = 0.0; // Source Side Inlet Temperature [C] diff --git a/tst/EnergyPlus/unit/VariableSpeedCoils.unit.cc b/tst/EnergyPlus/unit/VariableSpeedCoils.unit.cc index 08cef20d40d..4120a6eb945 100644 --- a/tst/EnergyPlus/unit/VariableSpeedCoils.unit.cc +++ b/tst/EnergyPlus/unit/VariableSpeedCoils.unit.cc @@ -6987,6 +6987,7 @@ TEST_F(EnergyPlusFixture, VariableSpeedCoils_Coil_Defrost_Power_Fix_Test) state->dataLoopNodes->Node(2).MassFlowRate = 0.2; state->dataVariableSpeedCoils->VarSpeedCoil(DXCoilNum).AirMassFlowRate = 0.2; state->dataEnvrn->OutDryBulbTemp = -5.0; + state->dataVariableSpeedCoils->VarSpeedCoil(DXCoilNum).FindCompanionUpStreamCoil = false; // Run a compressor "On" scenario first HVAC::CompressorOp compressorOp = HVAC::CompressorOp::On; @@ -7001,7 +7002,6 @@ TEST_F(EnergyPlusFixture, VariableSpeedCoils_Coil_Defrost_Power_Fix_Test) SensLoad, LatentLoad, OnOffAirFlowRatio); - EXPECT_NEAR(state->dataVariableSpeedCoils->VarSpeedCoil(DXCoilNum).DefrostPower, 908.10992432432420, 1e-3); // Real64 COPwDefrost = state->dataVariableSpeedCoils->VarSpeedCoil(DXCoilNum).COP; EXPECT_LT(state->dataVariableSpeedCoils->HeatingCapacityMultiplier, 1.0);