Class: OpenStudio::Model::FanVariableVolume

Inherits:
Object
  • Object
show all
Includes:
Fan, PrototypeFan
Defined in:
lib/openstudio-standards/prototypes/Prototype.FanVariableVolume.rb,
lib/openstudio-standards/standards/Standards.FanVariableVolume.rb,
lib/openstudio-standards/hvac_sizing/Siz.FanVariableVolume.rb

Overview

open the class to add methods to return sizing values

Instance Method Summary collapse

Methods included from Fan

#adjust_pressure_rise_to_meet_fan_power, #apply_standard_minimum_motor_efficiency, #baseline_impeller_efficiency, #brake_horsepower, #change_impeller_efficiency, #change_motor_efficiency, #fan_power, #motor_horsepower, #rated_w_per_cfm, #small_fan?, #standard_minimum_motor_efficiency_and_size

Methods included from PrototypeFan

#apply_prototype_fan_efficiency

Instance Method Details

#apply_prototype_fan_pressure_rise(building_type, template, climate_zone) ⇒ Object

Sets the fan pressure rise based on the Prototype buildings inputs which are governed by the flow rate coming through the fan and whether the fan lives inside a unit heater, PTAC, etc.



9
10
11
12
13
14
15
16
17
18
19
20
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
# File 'lib/openstudio-standards/prototypes/Prototype.FanVariableVolume.rb', line 9

def apply_prototype_fan_pressure_rise(building_type, template, climate_zone)
  # NECB
  if template == 'NECB 2011'
    pressure_rise_pa = 1458.33 # 1000 Pa for supply fan and 458.33 Pa for return fan (accounts for efficiency differences between two fans)
    setPressureRise(pressure_rise_pa)
    return true
  end

  # Get the max flow rate from the fan.
  maximum_flow_rate_m3_per_s = nil
  if maximumFlowRate.is_initialized
    maximum_flow_rate_m3_per_s = maximumFlowRate.get
  elsif autosizedMaximumFlowRate.is_initialized
    maximum_flow_rate_m3_per_s = autosizedMaximumFlowRate.get
  else
    OpenStudio.logFree(OpenStudio::Warn, 'openstudio.prototype.FanVariableVolume', "For #{name} max flow rate is not available, cannot apply prototype assumptions.")
    return false
  end

  # Convert max flow rate to cfm
  maximum_flow_rate_cfm = OpenStudio.convert(maximum_flow_rate_m3_per_s, 'm^3/s', 'cfm').get

  # Pressure rise will be determined based on the
  # following logic.
  pressure_rise_in_h2o = 0.0

  # If the fan lives inside of a zone hvac equipment
  if containingZoneHVACComponent.is_initialized
    zone_hvac = self.ZoneHVACComponent.get
    if zone_hvac.to_ZoneHVACPackagedTerminalAirConditioner.is_initialized
      pressure_rise_in_h2o = 1.33
    elsif zone_hvac.to_ZoneHVACFourPipeFanCoil.is_initialized
      pressure_rise_in_h2o = 1.33
    elsif zone_hvac.to_ZoneHVACUnitHeater.is_initialized
      pressure_rise_in_h2o = 0.2
    else # This type of fan should not exist in the prototype models
      return false
    end
  # If the fan lives on an airloop
  elsif airLoopHVAC.is_initialized

    # TODO: Inconsistency - Primary School uses CAV pressure rises
    # even thought it has a VAV system.  CAV system is listed in document,
    # so assume the system type was updated but forgot to update pressure rises.
    if building_type == 'PrimarySchool' && (template == 'DOE Ref Pre-1980' || template == 'DOE Ref 1980-2004')

      pressure_rise_in_h2o = if maximum_flow_rate_cfm < 7487
                               2.5
                             elsif maximum_flow_rate_cfm >= 7487 && maximum_flow_rate_cfm < 20_000
                               4.46
                             else # Over 20,000 cfm
                               4.09
                             end

    else

      case template
      when 'DOE Ref Pre-1980', 'DOE Ref 1980-2004', '90.1-2004'
        pressure_rise_in_h2o = if maximum_flow_rate_cfm < 4648
                                 4.0
                               elsif maximum_flow_rate_cfm >= 4648 && maximum_flow_rate_cfm < 20_000
                                 6.32
                               else # Over 20,000 cfm
                                 5.58
                               end
      when '90.1-2007', '90.1-2010', '90.1-2013'
        pressure_rise_in_h2o = if maximum_flow_rate_cfm < 4648
                                 4.0
                               else # Over 7,437 cfm
                                 5.58
                               end
      end

    end
  end

  # Set the fan pressure rise
  pressure_rise_pa = OpenStudio.convert(pressure_rise_in_h2o, 'inH_{2}O', 'Pa').get
  setPressureRise(pressure_rise_pa)

  OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.FanVariableVolume', "For Prototype: #{name}: #{maximum_flow_rate_cfm.round}cfm; Pressure Rise = #{pressure_rise_in_h2o}in w.c.")

  return true
end

#applySizingValuesObject

Takes the values calculated by the EnergyPlus sizing routines and puts them into this object model in place of the autosized fields. Must have previously completed a run with sql output for this to work.



13
14
15
16
17
18
19
20
# File 'lib/openstudio-standards/hvac_sizing/Siz.FanVariableVolume.rb', line 13

def applySizingValues
  
  maximum_flow_rate = self.autosizedMaximumFlowRate
  if maximum_flow_rate.is_initialized
    self.setMaximumFlowRate(maximum_flow_rate.get)
  end
  
end

#autosizeObject

Sets all auto-sizeable fields to autosize



6
7
8
# File 'lib/openstudio-standards/hvac_sizing/Siz.FanVariableVolume.rb', line 6

def autosize
  OpenStudio::logFree(OpenStudio::Warn, "openstudio.sizing.FanVariableVolume", ".autosize not yet implemented for #{self.iddObject.type.valueDescription}.")
end

#autosizedMaximumFlowRateObject

returns the autosized maximum flow rate as an optional double



23
24
25
26
27
# File 'lib/openstudio-standards/hvac_sizing/Siz.FanVariableVolume.rb', line 23

def autosizedMaximumFlowRate

  return self.model.getAutosizedValue(self, 'Design Size Maximum Flow Rate', 'm3/s')
  
end

#cooling_system_typeString

Determine if the cooling system is DX, CHW, evaporative, or a mixture. dx, chw, evaporative, mixed, unknown.

Returns:

  • (String)

    the cooling system type. Possible options are:



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/openstudio-standards/standards/Standards.FanVariableVolume.rb', line 145

def cooling_system_type
  clg_sys_type = 'unknown'

  # Get the air loop this fan is connected to
  air_loop = airLoopHVAC
  unless air_loop.is_initialized
    return clg_sys_type
  end
  air_loop = air_loop.get

  # Check the types of coils on the AirLoopHVAC
  has_dx = false
  has_chw = false
  has_evap = false
  air_loop.supplyComponents.each do |sc|
    # CoilCoolingDXSingleSpeed
    if sc.to_CoilCoolingDXSingleSpeed.is_initialized
      has_dx = true
    # CoilCoolingDXTwoSpeed
    elsif sc.to_CoilCoolingDXTwoSpeed.is_initialized
      has_dx = true
    # CoilCoolingMultiSpeed
    elsif sc.to_CoilCoolingDXMultiSpeed.is_initialized
      has_dx = true
    # CoilCoolingWater
    elsif sc.to_CoilCoolingWater.is_initialized
      has_chw = true
    # CoilCoolingWaterToAirHeatPumpEquationFit
    elsif sc.to_CoilCoolingWaterToAirHeatPumpEquationFit.is_initialized
      has_dx = true
    # UnitarySystem
    elsif sc.to_AirLoopHVACUnitarySystem.is_initialized
      unitary = sc.to_AirLoopHVACUnitarySystem.get
      if unitary.coolingCoil.is_initialized
        clg_coil = unitary.coolingCoil.get
        # CoilCoolingDXSingleSpeed
        if clg_coil.to_CoilCoolingDXSingleSpeed.is_initialized
          has_dx = true
        # CoilCoolingDXTwoSpeed
        elsif clg_coil.to_CoilCoolingDXTwoSpeed.is_initialized
          has_dx = true
        # CoilCoolingWater
        elsif clg_coil.to_CoilCoolingWater.is_initialized
          has_chw = true
        # CoilCoolingWaterToAirHeatPumpEquationFit
        elsif clg_coil.to_CoilCoolingWaterToAirHeatPumpEquationFit.is_initialized
          has_dx = true
        end
      end
    # UnitaryHeatPumpAirToAir
    elsif sc.to_AirLoopHVACUnitaryHeatPumpAirToAir.is_initialized
      unitary = sc.to_AirLoopHVACUnitaryHeatPumpAirToAir.get
      clg_coil = unitary.coolingCoil
      # CoilCoolingDXSingleSpeed
      if clg_coil.to_CoilCoolingDXSingleSpeed.is_initialized
        has_dx = true
      # CoilCoolingDXTwoSpeed
      elsif clg_coil.to_CoilCoolingDXTwoSpeed.is_initialized
        has_dx = true
      # CoilCoolingWater
      elsif clg_coil.to_CoilCoolingWater.is_initialized
        has_chw = true
      end
    # EvaporativeCoolerDirectResearchSpecial
    elsif sc.to_EvaporativeCoolerDirectResearchSpecial.is_initialized
      has_evap = true
    # EvaporativeCoolerIndirectResearchSpecial
    elsif sc.to_EvaporativeCoolerIndirectResearchSpecial.is_initialized
      has_evap = true
    elsif sc.to_CoilCoolingCooledBeam.is_initialized ||
          sc.to_AirLoopHVACUnitaryHeatCoolVAVChangeoverBypass.is_initialized ||
          sc.to_AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed.is_initialized ||
          sc.to_AirLoopHVACUnitarySystem.is_initialized
      OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.AirLoopHVAC', "#{air_loop.name} has a cooling coil named #{sc.name}, whose type is not yet covered by cooling system type checks.")
    end
  end

  # Determine the type
  if (has_chw && has_dx && has_evap) ||
    (has_chw && has_dx) ||
    (has_chw && has_evap) ||
    (has_dx && has_evap)
    clg_sys_type = 'mixed'
  elsif has_chw
    clg_sys_type = 'chw'
  elsif has_dx
    clg_sys_type = 'dx'
  elsif has_evap
    clg_sys_type = 'evap'
  end

  return clg_sys_type
end

#part_load_fan_power_limitation?(template) ⇒ Boolean

Determines whether there is a requirement to have a VSD or some other method to reduce fan power at low part load ratios.

Returns:

  • (Boolean)


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
138
139
140
# File 'lib/openstudio-standards/standards/Standards.FanVariableVolume.rb', line 86

def part_load_fan_power_limitation?(template)
   part_load_control_required = false

  # Not required by the old vintages
  if template == 'DOE Ref Pre-1980' || template == 'DOE Ref 1980-2004' || template == 'NECB 2011'
    return part_load_control_required
  end

  # Determine the motor size limit
  hp_limit = nil # No minimum limit
  cap_limit_btu_per_hr = nil # No minimum limit
  case template
  when '90.1-2004'
    hp_limit = 15.0
  when '90.1-2007', '90.1-2010'
    hp_limit = 10.0
  when '90.1-2013'
    case cooling_system_type
    when 'dx'
      hp_limit = 0.0
      cap_limit_btu_per_hr = 110_000
    when 'chw'
      hp_limit = 5.0
    when 'evap'
      hp_limit = 0.25
    else
      hp_limit = 9999.9 # No requirement
    end
  end

  # Check against limits
  if hp_limit && cap_limit_btu_per_hr
    air_loop = airLoopHVAC
    unless air_loop.is_initialized
      OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.AirLoopHVAC', "For #{name}: Could not find the air loop to get cooling capacity for determining part load fan power control requirement.")
      return part_load_control_required
    end
    air_loop = air_loop.get
    clg_cap_w = air_loop.total_cooling_capacity
    clg_cap_btu_per_hr = OpenStudio.convert(clg_cap_w, 'W', 'Btu/hr').get
    fan_hp = motor_horsepower
    if fan_hp >= hp_limit && clg_cap_btu_per_hr >= cap_limit_btu_per_hr
      OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{name}: part load fan power control is required for #{fan_hp.round(1)} HP fan, #{clg_cap_btu_per_hr.round} Btu/hr cooling capacity.")
      part_load_control_required = true
    end             
  elsif hp_limit
    fan_hp = motor_horsepower
    if fan_hp >= hp_limit
      OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{name}: Part load fan power control is required for #{fan_hp.round(1)} HP fan.")
      part_load_control_required = true
    end
  end

  return part_load_control_required
end

#set_control_type(control_type) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
# File 'lib/openstudio-standards/standards/Standards.FanVariableVolume.rb', line 6

def set_control_type(control_type)
  # Determine the coefficients
  coeff_a = nil
  coeff_b = nil
  coeff_c = nil
  coeff_d = nil
  min_pct_pwr = nil
  case control_type
  when 'Multi Zone VAV with AF or BI Riding Curve'
    coeff_a = 0.1631
    coeff_b = 1.5901
    coeff_c = -0.8817
    coeff_d = 0.1281
    min_pct_pwr = 0.7
  when 'Multi Zone VAV with AF or BI with Inlet Vanes'
    coeff_a = 0.9977
    coeff_b = -0.659
    coeff_c = 0.9547
    coeff_d = -0.2936
    min_pct_pwr = 0.5
  when 'Multi Zone VAV with FC Riding Curve'
    coeff_a = 0.1224
    coeff_b = 0.612
    coeff_c = 0.5983
    coeff_d = -0.3334
    min_pct_pwr = 0.3
  when 'Multi Zone VAV with FC with Inlet Vanes'
    coeff_a = 0.3038
    coeff_b = -0.7608
    coeff_c = 2.2729
    coeff_d = -0.8169
    min_pct_pwr = 0.3
  when 'Multi Zone VAV with Vane-axial with Variable Pitch Blades'
    coeff_a = 0.1639
    coeff_b = -0.4016
    coeff_c = 1.9909
    coeff_d = -0.7541
    min_pct_pwr = 0.2
  when 'Multi Zone VAV with VSD and Fixed SP Setpoint'
    coeff_a = 0.0013
    coeff_b = 0.1470
    coeff_c = 0.9506
    coeff_d = -0.0998
    min_pct_pwr = 0.2
  when 'Multi Zone VAV with VSD and Static Pressure Reset'
    coeff_a = 0.04076
    coeff_b = 0.0881
    coeff_c = -0.0729
    coeff_d = 0.9437
    min_pct_pwr = 0.1
  when 'Single Zone VAV Fan'
    coeff_a = 0.027828
    coeff_b = 0.026583
    coeff_c = -0.087069
    coeff_d = 1.030920
    min_pct_pwr = 0.1
  else
    OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.FanVariableVolume', "Fan control type '#{control_type}' not recognized, fan power coefficients will not be changed.")
    return false
  end

  OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.FanVariableVolume', "For #{name}: Set fan curve coefficients to reflect control type of '#{control_type}'.")

  # Set the coefficients
  setFanPowerCoefficient1(coeff_a)
  setFanPowerCoefficient2(coeff_b)
  setFanPowerCoefficient3(coeff_c)
  setFanPowerCoefficient4(coeff_d)

  # Set the fan minimum power
  setFanPowerMinimumFlowRateInputMethod('Fraction')
  setFanPowerMinimumFlowFraction(min_pct_pwr)

  # Append the control type to the fan name
  # self.setName("#{self.name} #{control_type}")
end