class ASHRAE9012004

This class holds methods that apply ASHRAE 90.1-2004 to a given model. @ref [References::ASHRAE9012004]

Attributes

template[R]

Public Class Methods

new() click to toggle source
# File lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.rb, line 8
def initialize
  @template = '90.1-2004'
  load_standards_database
end

Public Instance Methods

air_loop_hvac_demand_control_ventilation_limits(air_loop_hvac) click to toggle source

Determines the OA flow rates above which an economizer is required. Two separate rates, one for systems with an economizer and another for systems without.

@param air_loop_hvac [OpenStudio::Model::AirLoopHVAC] air loop @return [Array<Double>] [min_oa_without_economizer_cfm, min_oa_with_economizer_cfm]

# File lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirLoopHVAC.rb, line 100
def air_loop_hvac_demand_control_ventilation_limits(air_loop_hvac)
  min_oa_without_economizer_cfm = 3000
  min_oa_with_economizer_cfm = 0
  return [min_oa_without_economizer_cfm, min_oa_with_economizer_cfm]
end
air_loop_hvac_enable_supply_air_temperature_reset_delta(air_loop_hvac) click to toggle source

Determines supply air temperature (SAT) temperature. For 90.1-2007, 10 delta-F ®

@param air_loop_hvac [OpenStudio::Model::AirLoopHVAC] air loop @return [Double] the SAT reset amount in degrees Rankine

# File lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirLoopHVAC.rb, line 167
def air_loop_hvac_enable_supply_air_temperature_reset_delta(air_loop_hvac)
  sat_reset_r = 10.0
  return sat_reset_r
end
air_loop_hvac_energy_recovery_ventilator_flow_limit(air_loop_hvac, climate_zone, pct_oa) click to toggle source

Determine the airflow limits that govern whether or not an ERV is required. Based on climate zone and % OA.

@param air_loop_hvac [OpenStudio::Model::AirLoopHVAC] air loop @param climate_zone [String] ASHRAE climate zone, e.g. ‘ASHRAE 169-2013-4A’ @param pct_oa [Double] percentage of outdoor air @return [Double] the flow rate above which an ERV is required. if nil, ERV is never required.

# File lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirLoopHVAC.rb, line 179
def air_loop_hvac_energy_recovery_ventilator_flow_limit(air_loop_hvac, climate_zone, pct_oa)
  erv_cfm = if pct_oa < 0.7
              nil
            else
              # @todo Add exceptions (eg: e. cooling systems in climate zones 3C, 4C, 5B, 5C, 6B, 7 and 8 | d. Heating systems in climate zones 1 to 3)
              5000
            end

  return erv_cfm
end
air_loop_hvac_motorized_oa_damper_limits(air_loop_hvac, climate_zone) click to toggle source

Determine the air flow and number of story limits for whether motorized OA damper is required.

@param air_loop_hvac [OpenStudio::Model::AirLoopHVAC] air loop @param climate_zone [String] ASHRAE climate zone, e.g. ‘ASHRAE 169-2013-4A’ @return [Array<Double>] [minimum_oa_flow_cfm, maximum_stories]. If both nil, never required

# File lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirLoopHVAC.rb, line 121
def air_loop_hvac_motorized_oa_damper_limits(air_loop_hvac, climate_zone)
  case climate_zone
  when 'ASHRAE 169-2006-0A',
       'ASHRAE 169-2006-1A',
       'ASHRAE 169-2006-0B',
       'ASHRAE 169-2006-1B',
       'ASHRAE 169-2006-2A',
       'ASHRAE 169-2006-2B',
       'ASHRAE 169-2006-3A',
       'ASHRAE 169-2006-3B',
       'ASHRAE 169-2006-3C',
       'ASHRAE 169-2013-0A',
       'ASHRAE 169-2013-1A',
       'ASHRAE 169-2013-0B',
       'ASHRAE 169-2013-1B',
       'ASHRAE 169-2013-2A',
       'ASHRAE 169-2013-2B',
       'ASHRAE 169-2013-3A',
       'ASHRAE 169-2013-3B',
       'ASHRAE 169-2013-3C'
    minimum_oa_flow_cfm = 0
    maximum_stories = 999 # Any number of stories
  else
    minimum_oa_flow_cfm = 0
    maximum_stories = 3
  end

  return [minimum_oa_flow_cfm, maximum_stories]
end
air_loop_hvac_prm_baseline_economizer_required?(air_loop_hvac, climate_zone) click to toggle source

Determine if an economizer is required per the PRM.

@param air_loop_hvac [OpenStudio::Model::AirLoopHVAC] air loop @param climate_zone [String] ASHRAE climate zone, e.g. ‘ASHRAE 169-2013-4A’ @return [Boolean] returns true if required, false if not

# File lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirLoopHVAC.rb, line 9
def air_loop_hvac_prm_baseline_economizer_required?(air_loop_hvac, climate_zone)
  economizer_required = false

  # A big number of ft2 as the minimum requirement
  infinity_ft2 = 999_999_999_999
  min_int_area_served_ft2 = infinity_ft2
  min_ext_area_served_ft2 = infinity_ft2

  # Determine the minimum capacity that requires an economizer
  case climate_zone
  when 'ASHRAE 169-2006-0A',
       'ASHRAE 169-2006-1A',
       'ASHRAE 169-2006-0B',
       'ASHRAE 169-2006-1B',
       'ASHRAE 169-2006-2A',
       'ASHRAE 169-2006-3A',
       'ASHRAE 169-2006-4A',
       'ASHRAE 169-2013-0A',
       'ASHRAE 169-2013-1A',
       'ASHRAE 169-2013-0B',
       'ASHRAE 169-2013-1B',
       'ASHRAE 169-2013-2A',
       'ASHRAE 169-2013-3A',
       'ASHRAE 169-2013-4A'
    min_int_area_served_ft2 = infinity_ft2 # No requirement
    min_ext_area_served_ft2 = infinity_ft2 # No requirement
  when 'ASHRAE 169-2006-2B',
       'ASHRAE 169-2006-5A',
       'ASHRAE 169-2006-6A',
       'ASHRAE 169-2006-7A',
       'ASHRAE 169-2006-7B',
       'ASHRAE 169-2006-8A',
       'ASHRAE 169-2006-8B',
       'ASHRAE 169-2013-2B',
       'ASHRAE 169-2013-5A',
       'ASHRAE 169-2013-6A',
       'ASHRAE 169-2013-7A',
       'ASHRAE 169-2013-7B',
       'ASHRAE 169-2013-8A',
       'ASHRAE 169-2013-8B'
    min_int_area_served_ft2 = 15_000
    min_ext_area_served_ft2 = infinity_ft2 # No requirement
  when 'ASHRAE 169-2006-3B',
       'ASHRAE 169-2006-3C',
       'ASHRAE 169-2006-4B',
       'ASHRAE 169-2006-4C',
       'ASHRAE 169-2006-5B',
       'ASHRAE 169-2006-5C',
       'ASHRAE 169-2006-6B',
       'ASHRAE 169-2013-3B',
       'ASHRAE 169-2013-3C',
       'ASHRAE 169-2013-4B',
       'ASHRAE 169-2013-4C',
       'ASHRAE 169-2013-5B',
       'ASHRAE 169-2013-5C',
       'ASHRAE 169-2013-6B'
    min_int_area_served_ft2 = 10_000
    min_ext_area_served_ft2 = 25_000
  end

  # Check whether the system requires an economizer by comparing
  # the system capacity to the minimum capacity.
  min_int_area_served_m2 = OpenStudio.convert(min_int_area_served_ft2, 'ft^2', 'm^2').get
  min_ext_area_served_m2 = OpenStudio.convert(min_ext_area_served_ft2, 'ft^2', 'm^2').get

  # Get the interior and exterior area served
  int_area_served_m2 = air_loop_hvac_floor_area_served_interior_zones(air_loop_hvac)
  ext_area_served_m2 = air_loop_hvac_floor_area_served_exterior_zones(air_loop_hvac)

  # Check the floor area exception
  if int_area_served_m2 < min_int_area_served_m2 && ext_area_served_m2 < min_ext_area_served_m2
    if min_int_area_served_ft2 == infinity_ft2 && min_ext_area_served_ft2 == infinity_ft2
      OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: Economizer not required for climate zone #{climate_zone}.")
    else
      OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: Economizer not required for because the interior area served of #{int_area_served_m2} ft2 is less than the minimum of #{min_int_area_served_m2} and the perimeter area served of #{ext_area_served_m2} ft2 is less than the minimum of #{min_ext_area_served_m2} for climate zone #{climate_zone}.")
    end
    return economizer_required
  end

  # If here, economizer required
  economizer_required = true
  OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{air_loop_hvac.name}: Economizer required for the performance rating method baseline.")

  return economizer_required
end
air_loop_hvac_single_zone_controls_num_stages(air_loop_hvac, climate_zone) click to toggle source

Determine the number of stages that should be used as controls for single zone DX systems. 90.1-2004 requires 1 stage.

@param air_loop_hvac [OpenStudio::Model::AirLoopHVAC] air loop @param climate_zone [String] ASHRAE climate zone, e.g. ‘ASHRAE 169-2013-4A’ @return [Integer] the number of stages: 0, 1, 2

# File lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirLoopHVAC.rb, line 157
def air_loop_hvac_single_zone_controls_num_stages(air_loop_hvac, climate_zone)
  num_stages = 1
  return num_stages
end
air_loop_hvac_vav_damper_action(air_loop_hvac) click to toggle source

Determine whether the VAV damper control is single maximum or dual maximum control. Single Maximum for 90.1-2004.

@param air_loop_hvac [OpenStudio::Model::AirLoopHVAC] air loop @return [String] the damper control type: Single Maximum, Dual Maximum

# File lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirLoopHVAC.rb, line 111
def air_loop_hvac_vav_damper_action(air_loop_hvac)
  damper_action = 'Single Maximum'
  return damper_action
end
air_terminal_single_duct_vav_reheat_apply_initial_prototype_damper_position(air_terminal_single_duct_vav_reheat, zone_oa_per_area) click to toggle source

@!group AirTerminalSingleDuctVAVReheat Set the initial minimum damper position based on OA rate of the space and the template. Zones with low OA per area get lower initial guesses. Final position will be adjusted upward as necessary by Standards.AirLoopHVAC.apply_minimum_vav_damper_positions

@param air_terminal_single_duct_vav_reheat [OpenStudio::Model::AirTerminalSingleDuctVAVReheat] the air terminal object @param zone_oa_per_area [Double] the zone outdoor air per area in m^3/s*m^2 @return [Boolean] returns true if successful, false if not

# File lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirTerminalSingleDuctVAVReheat.rb, line 10
def air_terminal_single_duct_vav_reheat_apply_initial_prototype_damper_position(air_terminal_single_duct_vav_reheat, zone_oa_per_area)
  min_damper_position = 0.3

  # Set the minimum flow fraction
  air_terminal_single_duct_vav_reheat.setConstantMinimumAirFlowFraction(min_damper_position)

  return true
end
boiler_get_eff_fplr(boiler_hot_water) click to toggle source

Determine what part load efficiency degredation curve should be used for a boiler

@param boiler_hot_water [OpenStudio::Model::BoilerHotWater] hot water boiler object @return [String] returns name of the boiler curve to be used, or nil if not applicable

# File lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.BoilerHotWater.rb, line 6
def boiler_get_eff_fplr(boiler_hot_water)
  return 'Boiler with No Minimum Turndown'
end
fan_variable_volume_part_load_fan_power_limitation_hp_limit(fan_variable_volume) click to toggle source

The threhold horsepower below which part load control is not required. 15 nameplate HP threshold is equivalent to motors with input powers of 9.9 HP per TSD

@param fan_variable_volume [OpenStudio::Model::FanVariableVolume] variable volume fan object @return [Double] the limit, in horsepower. Return nil for no limit by default. @todo AddRef

# File lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.FanVariableVolume.rb, line 10
def fan_variable_volume_part_load_fan_power_limitation_hp_limit(fan_variable_volume)
  hp_limit = 9.9
  return hp_limit
end
load_standards_database(data_directories = []) click to toggle source

Loads the openstudio standards dataset for this standard.

@param data_directories [Array<String>] array of file paths that contain standards data @return [Hash] a hash of standards data

Calls superclass method ASHRAE901#load_standards_database
# File lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.rb, line 17
def load_standards_database(data_directories = [])
  super([__dir__] + data_directories)
end
model_get_percent_of_surface_range(model, wwr_parameter) click to toggle source

@!group Model

Determine the surface range of a baseline model. The method calculates the window to wall ratio (assuming all spaces are conditioned) and select the range based on the calculated window to wall ratio @param model [OpenStudio::Model::Model] OpenStudio model object @param wwr_parameter [Hash] parameters to choose min and max percent of surfaces,

could be different set in different standard
# File lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.Model.rb, line 10
def model_get_percent_of_surface_range(model, wwr_parameter)
  wwr_range = { 'minimum_percent_of_surface' => nil, 'maximum_percent_of_surface' => nil }
  intended_surface_type = wwr_parameter['intended_surface_type']
  # Do not process surfaces other than exterior windows and glass door for 2004 standard
  if intended_surface_type == 'ExteriorWindow' || intended_surface_type == 'GlassDoor'
    wwr = OpenstudioStandards::Geometry.model_get_exterior_window_to_wall_ratio(model)
    if wwr <= 0.1
      wwr_range['minimum_percent_of_surface'] = 1.0
      wwr_range['maximum_percent_of_surface'] = 10.0
    elsif wwr <= 0.2
      wwr_range['minimum_percent_of_surface'] = 10.001
      wwr_range['maximum_percent_of_surface'] = 20
    elsif wwr <= 0.3
      wwr_range['minimum_percent_of_surface'] = 20.001
      wwr_range['maximum_percent_of_surface'] = 30
    elsif wwr <= 0.4
      wwr_range['minimum_percent_of_surface'] = 30.001
      wwr_range['maximum_percent_of_surface'] = 40
    else
      wwr_range['minimum_percent_of_surface'] = 40.001
      wwr_range['maximum_percent_of_surface'] = 100.0
    end
  end
  return wwr_range
end
plant_loop_apply_prm_baseline_chilled_water_pumping_type(plant_loop) click to toggle source

Set the primary and secondary pumping control types for the chilled water loop, as specified in Appendix G.

@param plant_loop [OpenStudio::Model::PlantLoop] chilled water loop @return [Boolean] returns true if successful, false if not

# File lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.PlantLoop.rb, line 8
def plant_loop_apply_prm_baseline_chilled_water_pumping_type(plant_loop)
  # Determine the pumping type.
  minimum_area_ft2 = 120_000

  # Determine the area served
  area_served_m2 = plant_loop_total_floor_area_served(plant_loop)
  area_served_ft2 = OpenStudio.convert(area_served_m2, 'm^2', 'ft^2').get

  # Determine the primary pump type
  pri_control_type = 'Constant Flow'

  # Determine the secondary pump type
  sec_control_type = 'Riding Curve'
  if area_served_ft2 > minimum_area_ft2
    sec_control_type = 'VSD No Reset'
  end

  # Report out the pumping type
  unless pri_control_type.nil?
    OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{plant_loop.name}, primary pump type is #{pri_control_type}.")
  end

  unless sec_control_type.nil?
    OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{plant_loop.name}, secondary pump type is #{sec_control_type}.")
  end

  # Modify all the primary pumps
  plant_loop.supplyComponents.each do |sc|
    if sc.to_PumpVariableSpeed.is_initialized
      pump = sc.to_PumpVariableSpeed.get
      pump_variable_speed_set_control_type(pump, pri_control_type)
    elsif sc.to_HeaderedPumpsVariableSpeed.is_initialized
      pump = sc.to_HeaderedPumpsVariableSpeed.get
      headered_pump_variable_speed_set_control_type(pump, control_type)
    end
  end

  # Modify all the secondary pumps
  plant_loop.demandComponents.each do |sc|
    if sc.to_PumpVariableSpeed.is_initialized
      pump = sc.to_PumpVariableSpeed.get
      pump_variable_speed_set_control_type(pump, sec_control_type)
    elsif sc.to_HeaderedPumpsVariableSpeed.is_initialized
      pump = sc.to_HeaderedPumpsVariableSpeed.get
      headered_pump_variable_speed_set_control_type(pump, control_type)
    end
  end

  return true
end
pump_variable_speed_get_control_type(pump, plant_loop_type, pump_nominal_hp) click to toggle source

Determine type of pump part load control type @note code_sections [90.1-2004_6.5.4.1]

@param pump [OpenStudio::Model::PumpVariableSpeed] OpenStudio pump object @param plant_loop_type [String] Type of plant loop @param pump_nominal_hp [Float] Pump nominal horsepower @return [String] Pump part load control type

# File lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.PumpVariableSpeed.rb, line 11
def pump_variable_speed_get_control_type(pump, plant_loop_type, pump_nominal_hp)
  threshold = 50 # hp

  # Sizing factor to take into account that pumps
  # are typically sized to handle a ~10% pressure
  # increase and ~10% flow increase.
  design_sizing_factor = 1.25

  # Get pump head in Pa
  pump_head_pa = pump.ratedPumpHead

  return 'VSD No Reset' if pump_nominal_hp * design_sizing_factor > threshold && pump_head_pa > 300_000 # 100 ft. of head

  # else
  return 'Riding Curve'
end
space_infiltration_rate_75_pa(space = nil) click to toggle source

Baseline infiltration rate

@return [Double] the baseline infiltration rate, in cfm/ft^2 exterior above grade wall area at 75 Pa

# File lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.Space.rb, line 7
def space_infiltration_rate_75_pa(space = nil)
  basic_infil_rate_cfm_per_ft2 = 1.8
  return basic_infil_rate_cfm_per_ft2
end
thermal_zone_demand_control_ventilation_limits(thermal_zone) click to toggle source

Determine the area and occupancy level limits for demand control ventilation.

@param thermal_zone [OpenStudio::Model::ThermalZone] the thermal zone @return [Array<Double>] the minimum area, in m^2 and the minimum occupancy density in m^2/person. Returns nil if there is no requirement.

# File lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.ThermalZone.rb, line 11
def thermal_zone_demand_control_ventilation_limits(thermal_zone)
  min_area_ft2 = nil # No minimum area
  min_occ_per_1000_ft2 = 100

  # Convert to SI
  min_occ_per_ft2 = min_occ_per_1000_ft2 / 1000.0
  min_ft2_per_occ = 1.0 / min_occ_per_ft2
  min_m2_per_occ = OpenStudio.convert(min_ft2_per_occ, 'ft^2', 'm^2').get

  return [min_area_ft2, min_m2_per_occ]
end