Module: CoolingTower

Included in:
Standard
Defined in:
lib/openstudio-standards/standards/Standards.CoolingTower.rb

Overview

A variety of cooling tower methods that are the same regardless of type. These methods are available to CoolingTowerSingleSpeed, CoolingTowerTwoSpeed, and CoolingTowerVariableSpeed

CoolingTower collapse

Instance Method Details

#cooling_tower_apply_minimum_power_per_flow(cooling_tower) ⇒ Bool

Set the cooling tower fan power such that the tower hits the minimum performance (gpm/hp) specified by the standard. Note that in this case hp is motor nameplate hp, per 90.1. This method assumes that the fan brake horsepower is 90% of the motor nameplate hp. This method determines the minimum motor efficiency for the nameplate motor hp and sets the actual fan power by multiplying the brake horsepower by the efficiency. Thus the fan power used as an input to the simulation divided by the design flow rate will not (and should not) exactly equal the minimum tower performance.

Returns:

  • (Bool)

    true if successful, false if not



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/openstudio-standards/standards/Standards.CoolingTower.rb', line 21

def cooling_tower_apply_minimum_power_per_flow(cooling_tower)
  # Get the design water flow rate
  design_water_flow_m3_per_s = nil
  if cooling_tower.designWaterFlowRate.is_initialized
    design_water_flow_m3_per_s = cooling_tower.designWaterFlowRate.get
  elsif cooling_tower.autosizedDesignWaterFlowRate.is_initialized
    design_water_flow_m3_per_s = cooling_tower.autosizedDesignWaterFlowRate.get
  else
    OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoolingTower', "For #{cooling_tower.name} design water flow rate is not available, cannot apply efficiency standard.")
    return false
  end
  design_water_flow_gpm = OpenStudio.convert(design_water_flow_m3_per_s, 'm^3/s', 'gal/min').get

  # Get the table of cooling tower efficiencies
  heat_rejection = standards_data['heat_rejection']

  # Define the criteria to find the cooling tower properties
  # in the hvac standards data set.
  search_criteria = {}
  search_criteria['template'] = template

  # By definition cooling towers in E+ are open.
  # Closed cooling towers are the fluidcooler objects.
  search_criteria['equipment_type'] = 'Open Cooling Tower'

  # TODO: Standards replace this with a mechanism to store this
  # data in the cooling tower object itself.
  # For now, retrieve the fan type from the name
  name = cooling_tower.name.get
  fan_type = nil
  if name.include?('Centrifugal')
    fan_type = 'Centrifugal'
  elsif name.include?('Propeller or Axial')
    fan_type = 'Propeller or Axial'
  end
  unless fan_type.nil?
    search_criteria['fan_type'] = fan_type
  end

  # Limit on Centrifugal Fan
  # Open Circuit Cooling Towers.
  if fan_type == 'Centrifugal'
    gpm_limit = cooling_tower_apply_minimum_power_per_flow_gpm_limit(cooling_tower)
    if gpm_limit
      if design_water_flow_gpm >= gpm_limit
        fan_type = 'Propeller or Axial'
        search_criteria['fan_type'] = fan_type
        OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoolingTower', "For #{cooling_tower.name}, the design flow rate of #{design_water_flow_gpm.round} gpm is higher than the limit of #{gpm_limit.round} gpm for open centrifugal towers.  This tower must meet the minimum performance of #{fan_type} instead.")
      end
    end
  end

  # Get the cooling tower properties
  ct_props = model_find_object(heat_rejection, search_criteria)
  unless ct_props
    OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoolingTower', "For #{cooling_tower.name}, cannot find heat rejection properties, cannot apply standard efficiencies or curves.")
    return false
  end

  # Get cooling tower efficiency
  min_gpm_per_hp = ct_props['minimum_performance']
  OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoolingTower', "For #{cooling_tower.name}, design water flow = #{design_water_flow_gpm.round} gpm, minimum performance = #{min_gpm_per_hp} gpm/hp (nameplate).")

  # Calculate the allowed fan brake horsepower
  # per method used in PNNL prototype buildings.
  # Assumes that the fan brake horsepower is 90%
  # of the fan nameplate rated motor power.
  fan_motor_nameplate_hp = design_water_flow_gpm / min_gpm_per_hp
  fan_bhp = 0.9 * fan_motor_nameplate_hp

  # Lookup the minimum motor efficiency
  fan_motor_eff = 0.85
  motors = standards_data['motors']

  # Assuming all fan motors are 4-pole Enclosed
  search_criteria = {
    'template' => template,
    'number_of_poles' => 4.0,
    'type' => 'Enclosed'
  }

  motor_properties = model_find_object(motors, search_criteria, fan_motor_nameplate_hp)
  if motor_properties.nil?
    OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.CoolingTower', "For #{cooling_tower.name}, could not find motor properties using search criteria: #{search_criteria}, motor_hp = #{motor_hp} hp.")
    return false
  end

  fan_motor_eff = motor_properties['nominal_full_load_efficiency']
  nominal_hp = motor_properties['maximum_capacity'].to_f.round(1)
  # Round to nearest whole HP for niceness
  if nominal_hp >= 2
    nominal_hp = nominal_hp.round
  end

  # Calculate the fan motor power
  fan_motor_actual_power_hp = fan_bhp / fan_motor_eff
  # Convert to W
  fan_motor_actual_power_w = fan_motor_actual_power_hp * 745.7 # 745.7 W/HP

  OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.CoolingTower', "For #{cooling_tower.name}, allowed fan motor nameplate hp = #{fan_motor_nameplate_hp.round(1)} hp, fan brake horsepower = #{fan_bhp.round(1)}, and fan motor actual power = #{fan_motor_actual_power_hp.round(1)} hp (#{fan_motor_actual_power_w.round} W) at #{fan_motor_eff} motor efficiency.")

  # Append the efficiency to the name
  cooling_tower.setName("#{cooling_tower.name} #{min_gpm_per_hp.round(1)} gpm/hp")

  # Hard size the design fan power.
  # Leave the water flow and air flow autosized.
  if cooling_tower.to_CoolingTowerSingleSpeed.is_initialized
    cooling_tower.setFanPoweratDesignAirFlowRate(fan_motor_actual_power_w)
  elsif cooling_tower.to_CoolingTowerTwoSpeed.is_initialized
    cooling_tower.setHighFanSpeedFanPower(fan_motor_actual_power_w)
    cooling_tower.setLowFanSpeedFanPower(0.3 * fan_motor_actual_power_w)
  elsif cooling_tower.to_CoolingTowerVariableSpeed.is_initialized
    cooling_tower.setDesignFanPower(fan_motor_actual_power_w)
  end

  return true
end

#cooling_tower_apply_minimum_power_per_flow_gpm_limit(cooling_tower) ⇒ Double

Above this point, centrifugal fan cooling towers must meet the limits of propeller or axial cooling towers instead.

OpenStudio::Model::CoolingTowerTwoSpeed, OpenStudio::Model::CoolingTowerVariableSpeed] the cooling tower

Parameters:

Returns:

  • (Double)

    the limit, in gallons per minute. Return nil for no limit.



146
147
148
149
# File 'lib/openstudio-standards/standards/Standards.CoolingTower.rb', line 146

def cooling_tower_apply_minimum_power_per_flow_gpm_limit(cooling_tower)
  gpm_limit = nil
  return gpm_limit
end