class Standard # @!group Cooling Tower # Apply approach temperature sizing criteria to a condenser water loop # # @param condenser_loop [] a condenser loop served by a cooling tower # @param design_wet_bulb_c [Double] the outdoor design wetbulb conditions in degrees C def prototype_apply_condenser_water_temperatures(condenser_loop, design_wet_bulb_c: nil) sizing_plant = condenser_loop.sizingPlant loop_type = sizing_plant.loopType return false unless loop_type == 'Condenser' # if values are absent, use the CTI rating condition 78F if design_wet_bulb_c.nil? design_wet_bulb_c = OpenStudio.convert(78.0, 'F', 'C').get OpenStudio.logFree(OpenStudio::Warn, 'openstudio.Prototype.hvac_systems', "For condenser loop #{condenser_loop.name}, no design day OATwb conditions given. CTI rating condition of 78F OATwb will be used for sizing cooling towers.") end # EnergyPlus has a minimum limit of 68F and maximum limit of 80F for cooling towers design_wet_bulb_f = OpenStudio.convert(design_wet_bulb_c, 'C', 'F').get eplus_min_design_wet_bulb_f = 68.0 eplus_max_design_wet_bulb_f = 80.0 if design_wet_bulb_f < eplus_min_design_wet_bulb_f OpenStudio.logFree(OpenStudio::Warn, 'openstudio.Prototype.CoolingTower', "For condenser loop #{condenser_loop.name}, increased design OATwb from #{design_wet_bulb_f.round(1)} F to EneryPlus model minimum limit of #{eplus_min_design_wet_bulb_f} F.") design_wet_bulb_f = eplus_min_design_wet_bulb_f elsif design_wet_bulb_f > eplus_max_design_wet_bulb_f OpenStudio.logFree(OpenStudio::Warn, 'openstudio.Prototype.CoolingTower', "For condenser loop #{condenser_loop.name}, reduced design OATwb from #{design_wet_bulb_f.round(1)} F to EneryPlus model maximum limit of #{eplus_max_design_wet_bulb_f} F.") design_wet_bulb_f = eplus_max_design_wet_bulb_f end design_wet_bulb_c = OpenStudio.convert(design_wet_bulb_f, 'F', 'C').get # Determine the design CW temperature, approach, and range leaving_cw_t_c, approach_k, range_k = prototype_condenser_water_temperatures(design_wet_bulb_c) # Convert to IP units leaving_cw_t_f = OpenStudio.convert(leaving_cw_t_c, 'C', 'F').get approach_r = OpenStudio.convert(approach_k, 'K', 'R').get range_r = OpenStudio.convert(range_k, 'K', 'R').get # Report out design conditions OpenStudio.logFree(OpenStudio::Info, 'openstudio.Prototype.CoolingTower', "For condenser loop #{condenser_loop.name}, design OATwb = #{design_wet_bulb_f.round(1)} F, approach = #{approach_r.round(1)} deltaF, range = #{range_r.round(1)} deltaF, leaving condenser water temperature = #{leaving_cw_t_f.round(1)} F.") # Set Cooling Tower sizing parameters. # Only the variable speed cooling tower in E+ allows you to set the design temperatures. # # Per the documentation # http://bigladdersoftware.com/epx/docs/8-4/input-output-reference/group-condenser-equipment.html#field-design-u-factor-times-area-value # for CoolingTowerSingleSpeed and CoolingTowerTwoSpeed # E+ uses the following values during sizing: # 95F entering water temp # 95F OATdb # 78F OATwb # range = loop design delta-T aka range (specified above) condenser_loop.supplyComponents.each do |sc| if sc.to_CoolingTowerVariableSpeed.is_initialized ct = sc.to_CoolingTowerVariableSpeed.get ct.setDesignInletAirWetBulbTemperature(design_wet_bulb_c) ct.setDesignApproachTemperature(approach_k) ct.setDesignRangeTemperature(range_k) end end # Set the CW sizing parameters # EnergyPlus autosizing routine assumes 85F and 10F temperature difference energyplus_design_loop_exit_temperature_c = OpenStudio.convert(85.0, 'F', 'C').get sizing_plant.setDesignLoopExitTemperature(energyplus_design_loop_exit_temperature_c) sizing_plant.setLoopDesignTemperatureDifference(OpenStudio.convert(10.0, 'R', 'K').get) # Cooling Tower operational controls # G3.1.3.11 - Tower shall be controlled to maintain a 70F LCnWT where weather permits, # floating up to leaving water at design conditions. float_down_to_f = 70.0 float_down_to_c = OpenStudio.convert(float_down_to_f, 'F', 'C').get # get or create a setpoint manager cw_t_stpt_manager = nil condenser_loop.supplyOutletNode.setpointManagers.each do |spm| if spm.to_SetpointManagerFollowOutdoorAirTemperature.is_initialized if spm.name.get.include? 'Setpoint Manager Follow OATwb' cw_t_stpt_manager = spm.to_SetpointManagerFollowOutdoorAirTemperature.get end end end if cw_t_stpt_manager.nil? cw_t_stpt_manager = OpenStudio::Model::SetpointManagerFollowOutdoorAirTemperature.new(condenser_loop.model) cw_t_stpt_manager.addToNode(condenser_loop.supplyOutletNode) end cw_t_stpt_manager.setName("#{condenser_loop.name} Setpoint Manager Follow OATwb with #{approach_r.round(1)}F Approach") cw_t_stpt_manager.setReferenceTemperatureType('OutdoorAirWetBulb') # At low design OATwb, it is possible to calculate # a maximum temperature below the minimum. In this case, # make the maximum and minimum the same. if leaving_cw_t_c < float_down_to_c OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlantLoop', "For #{condenser_loop.name}, the maximum leaving temperature of #{leaving_cw_t_f.round(1)} F is below the minimum of #{float_down_to_f.round(1)} F. The maximum will be set to the same value as the minimum.") leaving_cw_t_c = float_down_to_c end cw_t_stpt_manager.setMaximumSetpointTemperature(leaving_cw_t_c) cw_t_stpt_manager.setMinimumSetpointTemperature(float_down_to_c) cw_t_stpt_manager.setOffsetTemperatureDifference(approach_k) end # Determine the performance rating method specified design condenser water temperature, approach, and range # # @param design_oat_wb_c [Double] the design OA wetbulb temperature (C) # @return [Array] [leaving_cw_t_c, approach_k, range_k] def prototype_condenser_water_temperatures(design_oat_wb_c) design_oat_wb_f = OpenStudio.convert(design_oat_wb_c, 'C', 'F').get # 90.1-2010 G3.1.3.11 - CW supply temp = 85F or 10F approaching design wet bulb temperature, whichever is lower. # Design range = 10F # Design Temperature rise of 10F => Range: 10F range_r = 10.0 # Determine the leaving CW temp max_leaving_cw_t_f = 85.0 leaving_cw_t_10f_approach_f = design_oat_wb_f + 10.0 leaving_cw_t_f = [max_leaving_cw_t_f, leaving_cw_t_10f_approach_f].min # Calculate the approach approach_r = leaving_cw_t_f - design_oat_wb_f # Convert to SI units leaving_cw_t_c = OpenStudio.convert(leaving_cw_t_f, 'F', 'C').get approach_k = OpenStudio.convert(approach_r, 'R', 'K').get range_k = OpenStudio.convert(range_r, 'R', 'K').get return [leaving_cw_t_c, approach_k, range_k] end end