-
Notifications
You must be signed in to change notification settings - Fork 460
Description
Issue overview
There are some differences between the code and the documentation on what temperature is used when comparing with a temperature threshold to determine the On/Off of a crankcase heater. In the documentation, water heaters use compressor temperature, others use outdoor temperature.
The documentation and temperature threshold idd field name
For the following objects, the outdoor dry-bulb temperature is used. The name of the temperature threshold is "Maximum Outdoor Dry-bulb Temperature for Crankcase Heater Operation". The documentation of the field is like this "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".
- Coil:Cooling:DX:CurveFit:Performance (calculated in
CoilCoolingDXCurveFitPerformance::simulate) - Coil:Cooling:DX:SingleSpeed (calculated in function
CalcDXHeatingCoil) - Coil:Cooling:DX:TwoStageWithHumidityControlMode (calculated in function
CalcDoe2DXCoil) - Coil:Cooling:DX:MultiSpeed (calculated in function
CalcMultiSpeedDXCoilCooling) - Coil:Cooling:DX:VariableSpeed (calculated in function
CalcVarSpeedCoilCooling) - Coil:Heating:DX:SingleSpeed (calculated in function
CalcDXHeatingCoil) - Coil:Heating:DX:MultiSpeed (calculated in function
CalcMultiSpeedDXCoilHeating) - Coil:Heating:DX:VariableSpeed (calculated in function
CalcVarSpeedCoilHeating)
For the following heat pump water heater object, the compressor ambient temperature is used. The name of the temperature threshold field is "Maximum Ambient Temperature for Crankcase Heater Operation". The documentation of the field is "The crankcase heater only operates when the compressor is off and the air surrounding the compressor is below the Maximum Ambient Temperature for Crankcase Heater Operation specified below."
- Coil:WaterHeating:AirToWaterHeatPump:Pumped (in function
CalcDoe2DXCoil) - Coil:WaterHeating:AirToWaterHeatPump:Wrapped (in function
CalcDoe2DXCoil) - Coil:WaterHeating:AirToWaterHeatPump:VariableSpeed (in function
CalcVarSpeedHPWH)
The code
in CoilCoolingDXCurveFitPerformance.cc, the threshold checks are as follows
in CoilCoolingDXCurveFitPerformance::simulate: state.dataEnvrn->OutDryBulbTemp < this->maxOutdoorDrybulbForBasin
in DXCoils.cc, the threshold checks are as follows
in function CalcDoe2DXCoil: CompAmbTemp < thisDXCoil.MaxOATCrankcaseHeater
in function CalcVRFCoolingCoil: CompAmbTemp < thisDXCoil.MaxOATCrankcaseHeater
in function CalcDXHeatingCoil: CompAmbTemp < thisDXCoil.MaxOATCrankcaseHeater
in function CalcMultiSpeedDXCoilCooling: OutdoorDryBulb < thisDXCoil.MaxOATCrankcaseHeater
in function CalcMultiSpeedDXCoilHeating: OutdoorDryBulb < thisDXCoil.MaxOATCrankcaseHeater
in function CalcVRFCoolingCoil_FluidTCtrl: CompAmbTemp < thisDXCoil.MaxOATCrankcaseHeater
in function CalcVRFHeatingCoil_FluidTCtrl: OutdoorDryBulb < thisDXCoil.MaxOATCrankcaseHeater
For the ones using OutdoorDryBulb temporary variables:
InCalcVRFHeatingCoil_FluidTCtrl, the temporary variable OutdoorDryBulb is just outdoor temperature. In CalcMultiSpeedDXCoilCooling and CalcMultiSpeedDXCoilHeating, OutdoorDryBulb is not actually the outdoor temperature in some cases. They could be condenser inlet node temperature (state.dataLoopNodes->Node(thisDXCoil.CondenserInletNodeNum(DXMode)).Temp), zone temperature (secZoneHB.ZT), or outdoor dry bulb temperature (state.dataEnvrn->OutDryBulbTemp). The following are related code chunks (only taking lines related to OutdoorDryBulb
// --------------------------------------------------------------------------------
// in CalcMultiSpeedDXCoilCooling
// --------------------------------------------------------------------------------
if (thisDXCoil.CondenserInletNodeNum(DXMode) != 0) {
if (OutdoorPressure == state.dataLoopNodes->DefaultNodeValues.Press) {
OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
} else {
OutdoorDryBulb = state.dataLoopNodes->Node(thisDXCoil.CondenserInletNodeNum(DXMode)).Temp;
}
if (thisDXCoil.IsSecondaryDXCoilInZone) {
OutdoorDryBulb = secZoneHB.ZT;
}
} else if (thisDXCoil.IsSecondaryDXCoilInZone) {
OutdoorDryBulb = secZoneHB.ZT;
} else {
OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
}
// --------------------------------------------------------------------------------
// in CalcMultiSpeedDXCoilHeating
// --------------------------------------------------------------------------------
if (thisDXCoil.CondenserInletNodeNum(1) != 0) {
if (OutdoorPressure == state.dataLoopNodes->DefaultNodeValues.Press) {
OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
} else {
OutdoorDryBulb = state.dataLoopNodes->Node(thisDXCoil.CondenserInletNodeNum(1)).Temp;
}
if (thisDXCoil.IsSecondaryDXCoilInZone) {
OutdoorDryBulb = secZoneHB.ZT;
}
} else if (thisDXCoil.IsSecondaryDXCoilInZone) {
OutdoorDryBulb = secZoneHB.ZT;
} else {
OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
}
// --------------------------------------------------------------------------------
// in CalcVRFHeatingCoil_FluidTCtrl
// --------------------------------------------------------------------------------
OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
For the ones using CompAmbTemp, it's a bit more complex. The following are code chunks related to how the CompAmbTemp is calculated. For most cases, a temporary variable OutdoorDryBulb is calculated (which might not be the actual outdoor temperature), then conditionally assigned to CompAmbTemp.
// in the following chunks, only lines related to OutdoorDryBulb or CompAmbTemp are extracted
// --------------------------------------------------------------------------------
// in function CalcDoe2DXCoil
// --------------------------------------------------------------------------------
if (thisDXCoil.CondenserType(Mode) != DataHeatBalance::RefrigCondenserType::WaterHeater) {
if (thisDXCoil.CondenserInletNodeNum(Mode) != 0) {
if (OutdoorPressure == state.dataLoopNodes->DefaultNodeValues.Press) {
OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
} else {
OutdoorDryBulb = state.dataLoopNodes->Node(thisDXCoil.CondenserInletNodeNum(Mode)).Temp;
}
} else {
OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
}
if (thisDXCoil.IsSecondaryDXCoilInZone) {
OutdoorDryBulb = secZoneHB.ZT;
}
} else {
}
if (thisDXCoil.CondenserType(Mode) == DataHeatBalance::RefrigCondenserType::Air) {
CompAmbTemp = OutdoorDryBulb;
if (thisDXCoil.IsSecondaryDXCoilInZone) {
CompAmbTemp = CondInletTemp; // assumes compressor is in same location as secondary coil
}
} else if (thisDXCoil.CondenserType(Mode) == DataHeatBalance::RefrigCondenserType::Evap) {
CompAmbTemp = OutdoorDryBulb;
} else if (thisDXCoil.CondenserType(Mode) == DataHeatBalance::RefrigCondenserType::WaterHeater) {
CompAmbTemp = state.dataHVACGlobal->HPWHCrankcaseDBTemp; // Temperature at HP water heater compressor
}
// --------------------------------------------------------------------------------
// in CalcVRFCoolingCoil
// --------------------------------------------------------------------------------
if (thisDXCoil.CondenserInletNodeNum(Mode) != 0) {
OutdoorDryBulb = state.dataLoopNodes->Node(thisDXCoil.CondenserInletNodeNum(Mode)).Temp;
if (thisDXCoil.CondenserType(Mode) == DataHeatBalance::RefrigCondenserType::Water) {
} else {
if (OutdoorPressure == state.dataLoopNodes->DefaultNodeValues.Press) {
OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
} else {
}
}
} else {
OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
}
if (thisDXCoil.CondenserType(Mode) == DataHeatBalance::RefrigCondenserType::Evap) {
CompAmbTemp = OutdoorDryBulb;
} else { // for air or water-cooled, inlet temp is stored in OutdoorDryBulb temp
if (thisDXCoil.CondenserType(Mode) == DataHeatBalance::RefrigCondenserType::Water) {
CompAmbTemp = state.dataEnvrn->OutDryBulbTemp; // for crankcase heater use actual outdoor temp for water-cooled
} else {
CompAmbTemp = OutdoorDryBulb;
}
}
// --------------------------------------------------------------------------------
// in CalcDXHeatingCoil
// --------------------------------------------------------------------------------
if (thisDXCoil.CondenserInletNodeNum(1) != 0) {
OutdoorDryBulb = state.dataLoopNodes->Node(thisDXCoil.CondenserInletNodeNum(1)).Temp;
CompAmbTemp = OutdoorDryBulb;
if (thisDXCoil.CondenserType(Mode) == DataHeatBalance::RefrigCondenserType::Water) {
CompAmbTemp = state.dataEnvrn->OutDryBulbTemp;
} else {
if (OutdoorPressure == state.dataLoopNodes->DefaultNodeValues.Press) {
OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
} else {
}
if (thisDXCoil.IsSecondaryDXCoilInZone) {
OutdoorDryBulb = secZoneHB.ZT;
CompAmbTemp = OutdoorDryBulb;
}
}
} else if (thisDXCoil.IsSecondaryDXCoilInZone) {
OutdoorDryBulb = secZoneHB.ZT;
CompAmbTemp = OutdoorDryBulb;
} else {
OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
CompAmbTemp = OutdoorDryBulb;
}
// --------------------------------------------------------------------------------
// in CalcMultiSpeedDXCoil
// --------------------------------------------------------------------------------
if (thisDXCoil.CondenserInletNodeNum(Mode) != 0) {
if (OutdoorPressure == state.dataLoopNodes->DefaultNodeValues.Press) {
OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
} else {
OutdoorDryBulb = state.dataLoopNodes->Node(thisDXCoil.CondenserInletNodeNum(Mode)).Temp;
}
CompAmbTemp = OutdoorDryBulb;
if (thisDXCoil.IsSecondaryDXCoilInZone) {
OutdoorDryBulb = secZoneHB.ZT;
CompAmbTemp = OutdoorDryBulb;
}
} else if (thisDXCoil.IsSecondaryDXCoilInZone) {
OutdoorDryBulb = secZoneHB.ZT;
CompAmbTemp = OutdoorDryBulb;
} else {
OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
CompAmbTemp = OutdoorDryBulb;
}
// --------------------------------------------------------------------------------
// in CalcVRFCoolingCoil_FluidTCtrl
// --------------------------------------------------------------------------------
if (thisDXCoil.CondenserInletNodeNum(Mode) != 0) {
OutdoorDryBulb = state.dataLoopNodes->Node(thisDXCoil.CondenserInletNodeNum(Mode)).Temp;
if (thisDXCoil.CondenserType(Mode) == DataHeatBalance::RefrigCondenserType::Water) {
} else {
if (OutdoorPressure == state.dataLoopNodes->DefaultNodeValues.Press) {
OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
} else {
}
}
} else {
OutdoorDryBulb = state.dataEnvrn->OutDryBulbTemp;
}
if (thisDXCoil.CondenserType(Mode) == DataHeatBalance::RefrigCondenserType::Evap) {
CompAmbTemp = OutdoorDryBulb;
} else { // for air or water-cooled, inlet temp is stored in OutdoorDryBulb temp
if (thisDXCoil.CondenserType(Mode) == DataHeatBalance::RefrigCondenserType::Water) {
CompAmbTemp = state.dataEnvrn->OutDryBulbTemp; // for crankcase heater use actual outdoor temp for water-cooled
} else {
CompAmbTemp = OutdoorDryBulb;
}
}
in VariableSpeedCoils.cc, the threshold checks are as follows.
- in function CalcVarSpeedHPWH:
state.dataEnvrn->OutDryBulbTemp < state.dataVariableSpeedCoils->VarSpeedCoil(DXCoilNum).MaxOATCrankcaseHeater - in function CalcVarSpeedCoilHeating:
state.dataVariableSpeedCoils->OutdoorDryBulb < state.dataVariableSpeedCoils->VarSpeedCoil(DXCoilNum).MaxOATCrankcaseHeater - in function CalcVarSpeedCoilCooling:
state.dataVariableSpeedCoils->OutdoorDryBulb_CalcVarSpeedCoilCooling <state.dataVariableSpeedCoils->VarSpeedCoil(DXCoilNum).MaxOATCrankcaseHeater
For the second and third case in the VariableSpeedCoils.cc, the *->OutdoorDryBulb equals to condenser inlet node temperature if the node is defined, otherwise it will be outdoor temperature
Details
Some additional details for this issue (if relevant):
- Platform (Operating system, version)
- Version of EnergyPlus (if using an intermediate build, include SHA)
- Unmethours link or helpdesk ticket number
Checklist
Add to this list or remove from it as applicable. This is a simple templated set of guidelines.
- Defect file added (list location of defect file here)
- Ticket added to Pivotal for defect (development team task)
- Pull request created (the pull request will have additional tasks related to reviewing changes that fix this defect)