module OpenstudioStandards::Infiltration
The Infiltration
module provides methods create, modify, and get information about model infiltration
The Infiltration
module provides methods create, modify, and get information about model infiltration
Public Class Methods
Convert an infiltration rate at a given pressure to another pressure (typically lower) Method from Gowri, Krishnan, Winiarski, David W, and Jarnagin, Ronald E. Infiltration
modeling guidelines for commercial building energy analysis. United States: N. p., 2009. Web. doi:10.2172/968203.
@param infiltration_rate [Double] initial infiltration rate @param initial_pressure [Double] pressure difference at which initial infiltration rate was determined, typically 75 Pa @param final_pressure [Double] desired pressure difference to adjust infiltration rate, typically 4 Pa @param infiltration_coefficient [Double] infiltration coeffiecient @return [Double] adjusted infiltration rate in the same units as infiltration_rate
# File lib/openstudio-standards/infiltration/infiltration.rb, line 14 def self.adjust_infiltration_to_new_pressure(infiltration_rate, initial_pressure: 75.0, final_pressure: 4.0, infiltration_coefficient: 0.65) adjusted_infiltration_rate = infiltration_rate * ((final_pressure / initial_pressure)**infiltration_coefficient) return adjusted_infiltration_rate end
Convert the infiltration rate to the pressures and conditions assumed in the PNNL prototype buildings Details described in Gowri, Krishnan, Winiarski, David W, and Jarnagin, Ronald E. Infiltration
modeling guidelines for commercial building energy analysis. United States: N. p., 2009. Web. doi:10.2172/968203.
@param infiltration_rate [Double] initial infiltration rate @param initial_pressure [Double] pressure difference at which initial infiltration rate was determined in Pa, default 75 Pa @return [Double] adjusted infiltration rate in the same units as infiltration_rate
# File lib/openstudio-standards/infiltration/infiltration.rb, line 29 def self.adjust_infiltration_to_prototype_building_conditions(infiltration_rate, initial_pressure: 75.0) alpha = 0.22 # terrain adjustment factor for an urban environment, unitless uh = 4.47 # wind speed, m/s rho = 1.18 # air density, kg/m^3 cs = 0.1617 # positive surface pressure coefficient, unitless n = 0.65 # infiltration coefficient, unitless # Calculate the typical pressure - same for all building types final_pressure_pa = 0.5 * cs * rho * (uh**2) adjusted_infiltration_rate = (1.0 + alpha) * infiltration_rate * ((final_pressure_pa / initial_pressure)**n) return adjusted_infiltration_rate end
Infer the building type to use for NIST correlations, as only a subset of building types are available.
@param model [OpenStudio::Model::Model] OpenStudio model object @return [OpenStudio::Model::Schedule] OpenStudio Schedule object
# File lib/openstudio-standards/infiltration/nist_infiltration.rb, line 30 def self.model_infer_nist_building_type(model) if model.getBuilding.standardsBuildingType.is_initialized model_building_type = model.getBuilding.standardsBuildingType.get else model_building_type = '' end case model_building_type when 'Office' # map office building type to small medium or large floor_area = model.getBuilding.floorArea if floor_area < 2750.0 nist_building_type = 'SmallOffice' else nist_building_type = 'MediumOffice' end when 'LargeOffice', 'Outpatient', 'OfL' nist_building_type = 'MediumOffice' when 'Retail' # map retal building type to RetailStripmall or RetailStandalone based on building name building_name = model.getBuilding.name.get if building_name.include? 'RetailStandalone' nist_building_type = 'RetailStandalone' else nist_building_type = 'RetailStripmall' end when 'StripMall', 'Warehouse', 'QuickServiceRestaurant', 'FullServiceRestaurant', 'RtS', 'RSD', 'RFF', 'SCn', 'SUn', 'WRf' nist_building_type = 'RetailStripmall' when 'SuperMarket', 'RtL' nist_building_type = 'RetailStandalone' when 'EPr' nist_building_type = 'PrimarySchool' when 'ESe' nist_building_type = 'SecondarySchool' when 'Mtl' nist_building_type = 'SmallHotel' when 'Htl' nist_building_type = 'LargeHotel' when 'Hsp' nist_building_type = 'Hospital' when 'OfS' nist_building_type = 'SmallOffice' else nist_building_type = model_building_type end OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "Using building type #{nist_building_type} for model building type #{model_building_type}.") return nist_building_type end
This method applies infiltration to a model that varies with weather and HVAC
operation, and takes into account building geometry (height, above-ground exterior surface area, and volume). It is based on work published by Ng et al. (2018) <a href=‘doi.org/10.1016/j.buildenv.2017.10.029’>‘Weather correlations to calculate infiltration rates for U.S. commercial building energy models’</a> and Ng et al. (2021) <a href=‘doi.org/10.1016/j.buildenv.2021.107783’>‘Evaluating potential benefits of air barriers in commercial buildings using NIST infiltration correlations in EnergyPlus’</a>. This method of calculating infiltration was developed using eleven of the DOE commercial prototype building models (<a href=‘www.energycodes.gov/development/commercial/prototype_models’>Goel et al. 2014</a>) and TMY3 weather files for eight climate zones (CZ). Guidance on implementing the infiltration correlations are explained in the NIST technical report <a href=‘doi.org/10.6028/NIST.TN.2221’>‘Implementing NIST Infiltration
Correlations’</a>. Ng et al. (2018) shows that when analyzing the benefits of building envelope airtightening, greater HVAC
energy savings were predicted using the infiltration inputs included in this method compared with using the default inputs that are included in the prototype building models. This method will remove any existing infiltration objects (OS:SpaceInfiltration:DesignFlowRate and OS:SpaceInfiltration:EffectiveLeakageArea). Every zone will then get two OS:SpaceInfiltration:DesignFlowRate objects that add infiltration using the ‘Flow per Exterior Surface Area’ input option, one infiltration object when the HVAC
system is on and one object when the HVAC
system is off. The method assumes that HVAC
operation is set by a schedule, though it may not reflect actual simulation/operation when fan operation may depend on internal loads and temperature setpoints. By default, interior zones will receive no infiltration. The user may enter a design building envelope airtightness at a specific design pressure, and whether the design value represents a 4-sided, 5-sided, or 6-sided normalization. By default, the method assumes an airtightness design value of 13.8 (m^3/h-m^2) at 75 Pa. The method assumes that infiltration is evenly distributed across the entire building envelope, including the roof. The user may select the HVAC
system operating schedule in the model, or infer it based on the availability schedule of the air loop that serves the largest amount of floor area. The method will make a copy of the HVAC
operating schedule, ‘Infiltration HVAC
On Schedule’, which is used with the HVAC
on infiltration correlations. The method will also make an ‘Infiltration HVAC
Off Schedule’ with inverse operation, used with the HVAC
off infiltration correlations. OS:SpaceInfiltration:DesignFlowRate object coefficients (A, B, C, and D) come from Ng et al. (2018). The user may select the Building Type and Climate Zone, or the method will infer them from the model. @author Matthew Dahlhausen <matthew.dahlhausen@nrel.gov>
@param model [OpenStudio::Model::Model] OpenStudio model object @param airtightness_value [Double] Airtightness design value (m^3/h-m^2).
The airtightness design value from a building pressurization test. Use 5.0 (m^3/h-m^2) as a default for buildings with air barriers. Convert (cfm/ft^2) to (m^3/h-m^2) by multiplying by 18.288 (m-min/ft-hr). (0.3048 m/ft)*(60 min/hr) = 18.288 (m-min/ft-hr).'
@param airtightness_pressure [Double] Airtightness design pressure (Pa).
The corresponding pressure for the airtightness design value, typically 75 Pa for commercial buildings and 50 Pa for residential buildings.
@param airtightness_area_covered [String] Airtightness exterior surface area scope.
Airtightness measurements are weighted by exterior surface area. 4-sided values divide infiltration by exterior wall area. 5-sided values additionally include roof area. 6-sided values additionally include floor and ground area.
@param air_barrier [Boolean] Does the building have an air barrier?
Buildings with air barriers use a different set of coefficients.
@param hvac_schedule_name [String] HVAC
Operating Schedule. Default will look up from model. @param nist_building_type [String] NIST building type. If the building type is not available, pick the one with the most similar geometry and exhaust fan flow rates. Default will lookup from model. @return [Boolean] returns true if successful, false if not
# File lib/openstudio-standards/infiltration/nist_infiltration.rb, line 97 def self.model_set_nist_infiltration(model, airtightness_value: 13.8, airtightness_pressure: 75.0, airtightness_area_covered: '5-sided', air_barrier: false, hvac_schedule_name: nil, nist_building_type: nil) # validate airtightness value and pressure if airtightness_value < 0.0 OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration', 'Airtightness value must be postive.') return false end if airtightness_pressure < 0.0 OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration', 'Airtightness pressure must be postive.') return false end # calculate infiltration design value at 4 Pa airtightness_value_4pa_per_hr = airtightness_value * ((4.0 / airtightness_pressure)**0.65) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "User-inputed airtightness design value #{airtightness_value} (m^3/h-m^2) at #{airtightness_pressure} Pa converts to #{airtightness_value_4pa_per_hr.round(7)} (m^3/h-m^2) at 4 Pa") # convert to m^3/s-m^2 airtightness_value_4pa_per_s = airtightness_value_4pa_per_hr / 3600.0 # get 4-sided, 5-sided, and 6-sided areas exterior_wall_area = 0.0 exterior_roof_area = 0.0 exterior_floor_area = 0.0 ground_wall_area = 0.0 ground_roof_area = 0.0 ground_floor_area = 0.0 model.getSurfaces.each do |surface| bc = surface.outsideBoundaryCondition type = surface.surfaceType area = surface.grossArea exterior_wall_area += area if bc == 'Outdoors' && type == 'Wall' exterior_roof_area += area if bc == 'Outdoors' && type == 'RoofCeiling' exterior_floor_area += area if bc == 'Outdoors' && type == 'Floor' ground_wall_area += area if bc == 'Ground' && type == 'Wall' ground_roof_area += area if bc == 'Ground' && type == 'RoofCeiling' ground_floor_area += area if bc == 'Ground' && type == 'Floor' end four_sided_area = exterior_wall_area + ground_wall_area five_sided_area = exterior_wall_area + ground_wall_area + exterior_roof_area + ground_roof_area six_sided_area = exterior_wall_area + ground_wall_area + exterior_roof_area + ground_roof_area + exterior_floor_area + ground_floor_area energy_plus_area = exterior_wall_area + exterior_roof_area OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "4-sided area = #{four_sided_area.round(2)} m^2, 5-sided area = #{five_sided_area.round(2)} m^2, 6-sided area = #{six_sided_area.round(2)} m^2.") # The SpaceInfiltrationDesignFlowRate object FlowperExteriorSurfaceArea method only counts surfaces with the 'Outdoors' boundary conditions towards exterior surface area, not surfaces with the 'Ground' boundary conditions. That means all values need to be normalized to exterior wall and roof area. case airtightness_area_covered when '4-sided' design_infiltration_4pa = airtightness_value_4pa_per_s * (four_sided_area / energy_plus_area) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "#{airtightness_area_covered} infiltration design value #{airtightness_value_4pa_per_s.round(7)} (m^3/s-m^2) converted to #{design_infiltration_4pa.round(7)} (m^3/s-m^2) based on 4-sided area #{four_sided_area.round(2)} m^2 and 5-sided area #{energy_plus_area.round(2)} m^2 excluding ground boundary surfaces for energyplus.") when '5-sided' design_infiltration_4pa = airtightness_value_4pa_per_s * (five_sided_area / energy_plus_area) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "#{airtightness_area_covered} infiltration design value #{airtightness_value_4pa_per_s.round(7)} (m^3/s-m^2) converted to #{design_infiltration_4pa.round(7)} (m^3/s-m^2) based on 5-sided area #{five_sided_area.round(2)} m^2 and 5-sided area #{energy_plus_area.round(2)} m^2 excluding ground boundary surfaces for energyplus.") when '6-sided' design_infiltration_4pa = airtightness_value_4pa_per_s * (six_sided_area / energy_plus_area) OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "#{airtightness_area_covered} infiltration design value #{airtightness_value_4pa_per_s.round(7)} (m^3/s-m^2) converted to #{design_infiltration_4pa.round(7)} (m^3/s-m^2) based on 6-sided area #{six_sided_area.round(2)} m^2 and 5-sided area #{energy_plus_area.round(2)} m^2 excluding ground boundary surfaces for energyplus.") end # validate hvac schedule if hvac_schedule_name.nil? hvac_schedule = OpenstudioStandards::Schedules.model_get_hvac_schedule(model) else hvac_schedule = model.getScheduleByName(hvac_schedule_name) unless hvac_schedule.is_initialized OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration', "HVAC schedule argument #{hvac_schedule} not found in the model. It may have been removed by another measure.") return false end hvac_schedule = hvac_schedule.get if hvac_schedule.to_ScheduleRuleset.is_initialized hvac_schedule = hvac_schedule.to_ScheduleRuleset.get elsif hvac_schedule.to_ScheduleConstant.is_initialized hvac_schedule = hvac_schedule.to_ScheduleConstant.get else OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration', "HVAC schedule argument #{hvac_schedule} is not a Schedule Constant or Schedule Ruleset object.") return false end OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "Using HVAC schedule #{hvac_schedule.name} from user arguments to determine infiltration on/off schedule.") end # creating infiltration schedules based on hvac schedule if hvac_schedule.nil? OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration', 'Unable to determine the building HVAC schedule. Treating the building as if there is no HVAC system with outdoor air. This may be appropriate for design sizing, particularly heating design sizing. If this is not the case, input a schedule argument, or assign one to an air loop in the model.') on_schedule = OpenStudio::Model::ScheduleConstant.new(model) on_schedule.setName('Infiltration HVAC On Schedule') on_schedule.setValue(0.0) off_schedule = OpenStudio::Model::ScheduleConstant.new(model) off_schedule.setName('Infiltration HVAC Off Schedule') off_schedule.setValue(1.0) elsif hvac_schedule.to_ScheduleConstant.is_initialized hvac_schedule = hvac_schedule.to_ScheduleConstant.get on_schedule = OpenStudio::Model::ScheduleConstant.new(model) on_schedule.setName('Infiltration HVAC On Schedule') on_schedule.setValue(hvac_schedule.value) off_schedule = OpenStudio::Model::ScheduleConstant.new(model) off_schedule.setName('Infiltration HVAC Off Schedule') if hvac_schedule.value > 0 off_schedule.setValue(0.0) else off_schedule.setValue(1.0) end elsif hvac_schedule.to_ScheduleRuleset.is_initialized hvac_schedule = hvac_schedule.to_ScheduleRuleset.get on_schedule = hvac_schedule.clone.to_ScheduleRuleset.get on_schedule.setName('Infiltration HVAC On Schedule') off_schedule = OpenstudioStandards::Schedules.create_inverted_schedule_ruleset(hvac_schedule, schedule_name: 'Infiltration HVAC Off Schedule') end # get climate zone number climate_zone_number = OpenstudioStandards::Weather.model_get_ashrae_climate_zone_number(model) # get nist building type if nist_building_type.nil? nist_building_type = model_infer_nist_building_type(model) end # check that model building type is supported unless nist_building_types.include? nist_building_type OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration', "NIST coefficients are not available for model building type #{nist_building_type}.") return false end # remove existing infiltration objects OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "The modeled started with #{model.getSpaceInfiltrationDesignFlowRates.size} infiltration objects and #{model.getSpaceInfiltrationEffectiveLeakageAreas.size} effective leakage area objects.") model.getSpaceInfiltrationDesignFlowRates.each(&:remove) model.getSpaceInfiltrationEffectiveLeakageAreas.each(&:remove) # load NIST infiltration correlations file and convert to hash table nist_infiltration_correlations_csv = "#{__dir__}/data/NISTInfiltrationCorrelations.csv" unless File.exist?(nist_infiltration_correlations_csv) OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration', "Unable to find file: #{nist_infiltration_correlations_csv}") return false end coefficients_tbl = CSV.table(nist_infiltration_correlations_csv, encoding: "ISO8859-1:utf-8" ) coefficients_hsh = coefficients_tbl.map(&:to_hash) # select down to building type and climate zone coefficients = coefficients_hsh.select { |r| (r[:building_type] == nist_building_type) && (r[:climate_zone] == climate_zone_number) } # filter by air barrier if air_barrier coefficients = coefficients.select { |r| r[:air_barrier] == 'yes' } else coefficients = coefficients.select { |r| r[:air_barrier] == 'no' } end # determine coefficients # if no off coefficients are defined, use 0 for a and the on coefficients for b and d on_coefficients = coefficients.select { |r| r[:hvac_status] == 'on' } off_coefficients = coefficients.select { |r| r[:hvac_status] == 'off' } a_on = on_coefficients[0][:a] b_on = on_coefficients[0][:b] d_on = on_coefficients[0][:d] a_off = off_coefficients[0][:a].nil? ? on_coefficients[0][:a] : off_coefficients[0][:a] b_off = off_coefficients[0][:b].nil? ? on_coefficients[0][:b] : off_coefficients[0][:b] d_off = off_coefficients[0][:d].nil? ? on_coefficients[0][:d] : off_coefficients[0][:d] # add new infiltration objects # define infiltration as flow per exterior area model.getSpaces.each do |space| next unless space.exteriorArea > 0.0 hvac_on_infiltration = OpenStudio::Model::SpaceInfiltrationDesignFlowRate.new(model) hvac_on_infiltration.setName("#{space.name.get} HVAC On Infiltration") hvac_on_infiltration.setFlowperExteriorSurfaceArea(design_infiltration_4pa) hvac_on_infiltration.setConstantTermCoefficient(a_on) hvac_on_infiltration.setTemperatureTermCoefficient(b_on) hvac_on_infiltration.setVelocityTermCoefficient(0.0) hvac_on_infiltration.setVelocitySquaredTermCoefficient(d_on) hvac_on_infiltration.setSpace(space) hvac_on_infiltration.setSchedule(on_schedule) hvac_off_infiltration = OpenStudio::Model::SpaceInfiltrationDesignFlowRate.new(model) hvac_off_infiltration.setName("#{space.name.get} HVAC Off Infiltration") hvac_off_infiltration.setFlowperExteriorSurfaceArea(design_infiltration_4pa) hvac_off_infiltration.setConstantTermCoefficient(a_off) hvac_off_infiltration.setTemperatureTermCoefficient(b_off) hvac_off_infiltration.setVelocityTermCoefficient(0.0) hvac_off_infiltration.setVelocitySquaredTermCoefficient(d_off) hvac_off_infiltration.setSpace(space) hvac_off_infiltration.setSchedule(off_schedule) end OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "The modeled finished with #{model.getSpaceInfiltrationDesignFlowRates.size} infiltration objects.") return true end
Loops through SpaceInfiltrationDesignFlowRate objects and adjusts the infiltration schedules to account building HVAC
operation
@param model [OpenStudio::Model::Model] OpenStudio model object @param hvac_schedule [OpenStudio::Model::Schedule] OpenStudio Schedule object for the HVAC
Operating Schedule. Default will look up from model. @return [Boolean] returns true if successful, false if not
# File lib/openstudio-standards/infiltration/nist_infiltration.rb, line 294 def self.model_set_nist_infiltration_schedules(model, hvac_schedule: nil) # delete existing schedules if present on_schedule = model.getScheduleByName('Infiltration HVAC On Schedule') on_schedule.get.remove if on_schedule.is_initialized off_schedule = model.getScheduleByName('Infiltration HVAC Off Schedule') off_schedule.get.remove if off_schedule.is_initialized # validate hvac schedule if hvac_schedule.nil? hvac_schedule = OpenstudioStandards::Schedules.model_get_hvac_schedule(model) else unless hvac_schedule.to_Schedule.is_initialized OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration', "HVAC schedule argument #{hvac_schedule} not found in the model or is not a Schedule object. It may have been removed by another measure.") return false end hvac_schedule = hvac_schedule.to_Schedule.get if hvac_schedule.to_ScheduleRuleset.is_initialized hvac_schedule = hvac_schedule.to_ScheduleRuleset.get elsif hvac_schedule.to_ScheduleConstant.is_initialized hvac_schedule = hvac_schedule.to_ScheduleConstant.get else OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration', "HVAC schedule argument #{hvac_schedule} is not a Schedule Constant or Schedule Ruleset object.") return false end OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "Using HVAC schedule #{hvac_schedule.name} from user arguments to determine infiltration on/off schedule.") end # creating infiltration schedules based on hvac schedule if hvac_schedule.nil? OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration', 'Unable to determine the HVAC schedule. Treating the building as if there is no HVAC system with outdoor air. If this is not the case, input a schedule argument, or assign one to an air loop in the model.') on_schedule = OpenStudio::Model::ScheduleConstant.new(model) on_schedule.setName('Infiltration HVAC On Schedule') on_schedule.setValue(0.0) off_schedule = OpenStudio::Model::ScheduleConstant.new(model) off_schedule.setName('Infiltration HVAC Off Schedule') off_schedule.setValue(1.0) elsif hvac_schedule.to_ScheduleConstant.is_initialized hvac_schedule = hvac_schedule.to_ScheduleConstant.get on_schedule = OpenStudio::Model::ScheduleConstant.new(model) on_schedule.setName('Infiltration HVAC On Schedule') on_schedule.setValue(hvac_schedule.value) off_schedule = OpenStudio::Model::ScheduleConstant.new(model) off_schedule.setName('Infiltration HVAC Off Schedule') if hvac_schedule.value > 0 off_schedule.setValue(0.0) else off_schedule.setValue(1.0) end elsif hvac_schedule.to_ScheduleRuleset.is_initialized hvac_schedule = hvac_schedule.to_ScheduleRuleset.get on_schedule = hvac_schedule.clone.to_ScheduleRuleset.get on_schedule.setName('Infiltration HVAC On Schedule') off_schedule = OpenstudioStandards::Schedules.create_inverted_schedule_ruleset(hvac_schedule, schedule_name: 'Infiltration HVAC Off Schedule') end model.getSpaceInfiltrationDesignFlowRates.each do |infil| if infil.name.get.include?('HVAC On Infiltration') infil.setSchedule(on_schedule) end if infil.name.get.include?('HVAC Off Infiltration') infil.setSchedule(off_schedule) end end return true end
DOE prototype buildings for which there are NIST infiltration coefficients.
@return [OpenStudio::StringVector] vector of strings of valid building types
# File lib/openstudio-standards/infiltration/nist_infiltration.rb, line 9 def self.nist_building_types building_types = OpenStudio::StringVector.new building_types << 'SecondarySchool' building_types << 'PrimarySchool' building_types << 'SmallOffice' building_types << 'MediumOffice' building_types << 'SmallHotel' building_types << 'LargeHotel' building_types << 'RetailStandalone' building_types << 'RetailStripmall' building_types << 'Hospital' building_types << 'MidriseApartment' building_types << 'HighriseApartment' return building_types end
Determine the component infiltration rate for a sub surface Details described in Table 5.7 of Thornton, Brian A, Rosenberg, Michael I, Richman, Eric E, Wang, Weimin, Xie, YuLong, Zhang, Jian, Cho, Heejin, Mendon, Vrushali V, Athalye, Rahul A, and Liu, Bing. Achieving the 30% Goal: Energy and Cost Savings Analysis of ASHRAE Standard
90.1-2010. United States: N. p., 2011. Web. doi:10.2172/1015277.
@param sub_surface [OpenStudio::Model::SubSurface] OpenStudio SubSurface object @param type [String] choices are ‘baseline’ and ‘advanced’ @return [Double] component infiltration rate in m^3/s
# File lib/openstudio-standards/infiltration/infiltration.rb, line 124 def self.sub_surface_component_infiltration_rate(sub_surface, type: 'baseline') # Define the envelope component infiltration rates component_infil_rates_cfm_per_ft2 = { 'baseline' => { 'opaque_door' => 0.40, 'loading_dock_door' => 0.40, 'swinging_or_revolving_glass_door' => 1.0, 'vestibule' => 1.0, 'sliding_glass_door' => 0.40, 'window' => 0.40, 'skylight' => 0.40 }, 'advanced' => { 'opaque_door' => 0.20, 'loading_dock_door' => 0.20, 'swinging_or_revolving_glass_door' => 1.0, 'vestibule' => 1.0, 'sliding_glass_door' => 0.20, 'window' => 0.20, 'skylight' => 0.20 } } # Skip non-outdoor surfaces unless sub_surface.outsideBoundaryCondition == 'Outdoors' return 0.0 end # Per area infiltration rate for this sub surface case sub_surface.subSurfaceType when 'Door' infil_rate_cfm_per_ft2 = component_infil_rates_cfm_per_ft2[type]['opaque_door'] when 'OverheadDoor' infil_rate_cfm_per_ft2 = component_infil_rates_cfm_per_ft2[type]['loading_dock_door'] when 'GlassDoor' OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "Assuming swinging_or_revolving_glass_door for #{sub_surface.name} for component infiltration rate.") infil_rate_cfm_per_ft2 = component_infil_rates_cfm_per_ft2[type]['swinging_or_revolving_glass_door'] when 'FixedWindow', 'OperableWindow' infil_rate_cfm_per_ft2 = component_infil_rates_cfm_per_ft2[type]['window'] when 'Skylight', 'TubularDaylightDome', 'TubularDaylightDiffuser' infil_rate_cfm_per_ft2 = component_infil_rates_cfm_per_ft2[type]['skylight'] else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration', "Could not determine infiltration sub surface type for #{sub_surface.name}, defaulting to 0 component infiltration rate.") return 0.0 end # Area of the sub surface area_m2 = sub_surface.netArea area_ft2 = OpenStudio.convert(area_m2, 'm^2', 'ft^2').get # Rate for this sub surface comp_infil_rate_cfm = area_ft2 * infil_rate_cfm_per_ft2 comp_infil_rate_m3_per_s = OpenStudio.convert(comp_infil_rate_cfm, 'cfm', 'm^3/s').get return comp_infil_rate_m3_per_s end
Determine the component infiltration rate for a surface Details described in Table 5.7 of Thornton, Brian A, Rosenberg, Michael I, Richman, Eric E, Wang, Weimin, Xie, YuLong, Zhang, Jian, Cho, Heejin, Mendon, Vrushali V, Athalye, Rahul A, and Liu, Bing. Achieving the 30% Goal: Energy and Cost Savings Analysis of ASHRAE Standard
90.1-2010. United States: N. p., 2011. Web. doi:10.2172/1015277.
@param surface [OpenStudio::Model::Surface] OpenStudio Surface object @param type [String] choices are ‘baseline’ and ‘advanced’ @return [Double] component infiltration rate in m^3/s
# File lib/openstudio-standards/infiltration/infiltration.rb, line 53 def self.surface_component_infiltration_rate(surface, type: 'baseline') # Define the envelope component infiltration rates component_infil_rates_cfm_per_ft2 = { 'baseline' => { 'roof' => 0.12, 'exterior_wall' => 0.12, 'below_grade_wall' => 0.12, 'floor_over_unconditioned' => 0.12, 'slab_on_grade' => 0.12 }, 'advanced' => { 'roof' => 0.04, 'exterior_wall' => 0.04, 'below_grade_wall' => 0.04, 'floor_over_unconditioned' => 0.04, 'slab_on_grade' => 0.04 } } # Skip non-outdoor surfaces boundary_condition = surface.outsideBoundaryCondition unless boundary_condition == 'Outdoors' || boundary_condition == 'Ground' return 0.0 end # Per area infiltration rate for this surface surface_type = surface.surfaceType infil_rate_cfm_per_ft2 = nil case boundary_condition when 'Outdoors' case surface_type when 'RoofCeiling' infil_rate_cfm_per_ft2 = component_infil_rates_cfm_per_ft2[type]['roof'] when 'Wall' infil_rate_cfm_per_ft2 = component_infil_rates_cfm_per_ft2[type]['exterior_wall'] when 'Floor' infil_rate_cfm_per_ft2 = component_infil_rates_cfm_per_ft2[type]['floor_over_unconditioned'] end when 'Ground' case surface_type when 'Wall' infil_rate_cfm_per_ft2 = component_infil_rates_cfm_per_ft2[type]['below_grade_wall'] when 'Floor' infil_rate_cfm_per_ft2 = component_infil_rates_cfm_per_ft2[type]['slab_on_grade'] end else OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration', "Could not determine infiltration surface type for #{surface.name}, defaulting to 0 component infiltration rate.") return 0.0 end # Area of the surface area_m2 = surface.netArea area_ft2 = OpenStudio.convert(area_m2, 'm^2', 'ft^2').get # Rate for this surface comp_infil_rate_cfm = area_ft2 * infil_rate_cfm_per_ft2 comp_infil_rate_m3_per_s = OpenStudio.convert(comp_infil_rate_cfm, 'cfm', 'm^3/s').get return comp_infil_rate_m3_per_s end