class ASHRAE901PRM2019

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

Attributes

template[R]

Public Class Methods

new() click to toggle source
Calls superclass method ASHRAE901PRM::new
# File lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.rb, line 8
def initialize
  super()
  @template = '90.1-PRM-2019'
  load_standards_database
end

Public Instance Methods

load_standards_database(data_directories = []) click to toggle source
Calls superclass method ASHRAE901PRM#load_standards_database
# File lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.rb, line 14
def load_standards_database(data_directories = [])
  super([__dir__] + data_directories)
end
model_apply_userdata_outdoor_air(model) click to toggle source

Function applies user specified OA to the model @param model [OpenStudio::Model::Model] model object @return [Boolean] returns true if successful, false if not

# File lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.DesignSpecificationOutdoorAir.rb, line 8
def model_apply_userdata_outdoor_air(model)
  # Step 1: Create a hash that maps design_spec_oa to a list of spaces
  # Also create a map that maps each design_spec_oa name to design_spec_oa.
  oa_spec_to_spaces = {}
  oa_spec_hash = {}
  model.getSpaces.each do |space|
    oa_spec = space.designSpecificationOutdoorAir
    if oa_spec.is_initialized
      oa_spec = oa_spec.get
      oa_spec_name = oa_spec.name.get
      unless oa_spec_to_spaces.key?(oa_spec_name)
        # init oa_spec_name associate zone name list.
        oa_spec_to_spaces[oa_spec_name] = []
      end
      unless oa_spec_hash.key?(oa_spec_name)
        # init the map of oa_spec_name to oa_spec object
        oa_spec_hash[oa_spec_name] = oa_spec
      end
      oa_spec_to_spaces[oa_spec_name].push(space)
    end
  end

  # Step 2: Loop the hash (oa_spec_name -> space_lists)
  oa_spec_to_spaces.each do |oa_spec_name, space_list|
    design_spec_oa = oa_spec_hash[oa_spec_name]
    if design_spec_oa.additionalProperties.hasFeature('has_user_data')
      outdoor_air_method = design_spec_oa.outdoorAirMethod

      outdoor_airflow_per_person = get_additional_property_as_double(design_spec_oa, 'outdoor_airflow_per_person')
      outdoor_airflow_per_floor_area = get_additional_property_as_double(design_spec_oa, 'outdoor_airflow_per_floor_area')
      outdoor_air_flowrate = get_additional_property_as_double(design_spec_oa, 'outdoor_air_flowrate')
      outdoor_air_flow_air_changes_per_hour = get_additional_property_as_double(design_spec_oa, 'outdoor_air_flow_air_changes_per_hour')

      # Area SQL - TabularDataWithStrings -> InputVerificationResultsSummary -> Entire Facility -> Zone Summary -> Zone Name -> Area
      total_modeled_area_oa = 0.0 # m2
      total_user_area_oa = 0.0 # m2
      total_modeled_people_oa = 0.0 # m3/s-person
      total_user_people_oa = 0.0 # m3/s-person
      total_modeled_airflow_oa = 0.0 # m3/s
      total_user_airflow_oa = 0.0 # m3/s
      total_modeled_ach_oa = 0.0 # ach
      total_user_ach_oa = 0.0 # ach
      space_list.each do |space|
        floor_area = space.floorArea
        volume = space.volume
        number_people = space.numberOfPeople
        total_modeled_area_oa += floor_area * design_spec_oa.outdoorAirFlowperFloorArea
        total_user_area_oa += floor_area * outdoor_airflow_per_floor_area

        total_modeled_people_oa += number_people * design_spec_oa.outdoorAirFlowperPerson
        total_user_people_oa += number_people * outdoor_airflow_per_person

        total_modeled_airflow_oa += design_spec_oa.outdoorAirFlowRate
        total_user_airflow_oa += outdoor_air_flowrate
        # convert to m3/s -> ach * volume / 3600
        total_modeled_ach_oa += design_spec_oa.outdoorAirFlowAirChangesperHour * volume / 3600
        total_user_ach_oa += outdoor_air_flow_air_changes_per_hour * volume / 3600
      end

      # calculate the amount of total outdoor air
      if outdoor_air_method.casecmp('sum') == 0
        total_modeled_airflow = total_modeled_area_oa + total_modeled_people_oa + total_modeled_airflow_oa + total_modeled_ach_oa
        total_user_airflow = total_user_area_oa + total_user_people_oa + total_user_airflow_oa + total_user_ach_oa
      elsif outdoor_air_method.casecmp('maximum') == 0
        total_modeled_airflow = [total_modeled_area_oa, total_modeled_people_oa, total_modeled_airflow_oa, total_modeled_ach_oa].max
        total_user_airflow = [total_user_area_oa, total_user_people_oa, total_user_airflow_oa, total_user_ach_oa].max
      else
        # No outdoor air method specified or match to the options available in OpenStudio
        # Raise exception to flag the modeling error
        error_msg = "DesignSpecification:OutdoorAir: #{design_spec_oa.name.get} is missing a method or the method is not one of the options {'Maximum', 'Sum'}."
        OpenStudio.logFree(OpenStudio::Warn, 'prm.log', error_msg)
        prm_raise(false,
                  @sizing_run_dir,
                  error_msg)
      end

      if total_modeled_airflow < total_user_airflow
        # Do not modify the model outdoor air if the total user airflow is lower than total modeled airflow
        OpenStudio.logFree(OpenStudio::Warn, 'prm.log', "The calculated total airflow for DesignSpecification:OutdoorAir is #{total_modeled_airflow} m3/s, which is smaller than the calculated user total airflow #{total_user_airflow} m3/s. Skip modifying the Outdoor Air.")
      else
        # set values.
        design_spec_oa.setOutdoorAirFlowperFloorArea(outdoor_airflow_per_floor_area)
        OpenStudio.logFree(OpenStudio::Info, 'prm.log', "Update DesignSpecification:OutdoorAir #{oa_spec_name} Outdoor Air Flow Per Floor Area to #{outdoor_airflow_per_floor_area} m3/s-m2.")
        design_spec_oa.setOutdoorAirFlowperPerson(outdoor_airflow_per_person)
        OpenStudio.logFree(OpenStudio::Info, 'prm.log', "Update DesignSpecification:OutdoorAir #{oa_spec_name} Outdoor Air Flow Per Person to #{outdoor_airflow_per_person} m3/s-person.")
        design_spec_oa.setOutdoorAirFlowRate(outdoor_air_flowrate)
        OpenStudio.logFree(OpenStudio::Info, 'prm.log', "Update DesignSpecification:OutdoorAir #{oa_spec_name} Outdoor Air Flow Rate to #{outdoor_air_flowrate} m3/s.")
        design_spec_oa.setOutdoorAirFlowAirChangesperHour(outdoor_air_flow_air_changes_per_hour)
        OpenStudio.logFree(OpenStudio::Info, 'prm.log', "Update DesignSpecification:OutdoorAir #{oa_spec_name} Outdoor Air ACH to #{outdoor_air_flow_air_changes_per_hour}.")
      end
    end
  end
end
model_create_prm_baseline_building_requires_proposed_model_sizing_run(model) click to toggle source

Determine if there is a need for a proposed model sizing run. A typical application of such sizing run is to determine space conditioning type.

@param model [OpenStudio::Model::Model] OpenStudio model object

@return [Boolean] Returns true if a sizing run is required

# File lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.Model.rb, line 11
def model_create_prm_baseline_building_requires_proposed_model_sizing_run(model)
  return true
end
model_get_percent_of_surface_range(model, wwr_parameter) click to toggle source

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_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.Model.rb, line 29
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']
  if intended_surface_type == 'ExteriorWindow' || intended_surface_type == 'GlassDoor'
    if wwr_parameter.key?('wwr_building_type')
      wwr_building_type = wwr_parameter['wwr_building_type']
      wwr_info = wwr_parameter['wwr_info']
      if wwr_info[wwr_building_type] <= 10
        wwr_range['minimum_percent_of_surface'] = 0
        wwr_range['maximum_percent_of_surface'] = 10
      elsif wwr_info[wwr_building_type] <= 20
        wwr_range['minimum_percent_of_surface'] = 10.001
        wwr_range['maximum_percent_of_surface'] = 20
      elsif wwr_info[wwr_building_type] <= 30
        wwr_range['minimum_percent_of_surface'] = 20.001
        wwr_range['maximum_percent_of_surface'] = 30
      elsif wwr_info[wwr_building_type] <= 40
        wwr_range['minimum_percent_of_surface'] = 30.001
        wwr_range['maximum_percent_of_surface'] = 40
      else
        wwr_range['minimum_percent_of_surface'] = nil
        wwr_range['maximum_percent_of_surface'] = nil
      end
    else
      OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', 'No wwr_building_type found for ExteriorWindow or GlassDoor')
    end
  end
  return wwr_range
end
model_prm_skylight_to_roof_ratio_limit(model) click to toggle source

Determines the skylight to roof ratio limit for a given standard 3% for 90.1-PRM-2019 @return [Double] the skylight to roof ratio, as a percent: 5.0 = 5%

# File lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.Model.rb, line 18
def model_prm_skylight_to_roof_ratio_limit(model)
  srr_lim = 3.0
  return srr_lim
end
space_infiltration_rate_75_pa(space = nil) click to toggle source

Determine the base infiltration rate at 75 PA.

@param space [OpenStudio::Model::Space] space object @return [Double] the baseline infiltration rate, in cfm/ft^2 defaults to no infiltration.

# File lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.rb, line 23
def space_infiltration_rate_75_pa(space = nil)
  basic_infil_rate_cfm_per_ft2 = 1.0
  return basic_infil_rate_cfm_per_ft2
end