module OpenstudioStandards::Constructions
The Constructions
module provides methods create, modify, and get information about model Constructions
The Constructions
module provides methods create, modify, and get information about model Constructions
The Constructions
module provides methods create, modify, and get information about model Constructions
The Constructions
module provides methods create, modify, and get information about model Constructions
The Constructions
module provides methods create, modify, and get information about model Constructions
Public Class Methods
add new material layer to a construction
@param construction [OpenStudio::Model::Construction] OpenStudio Construction object @param layer_index [Integer] the layer index, default is 0 @param name [String] name of the new material layer @param roughness [String] surface roughness of the new material layer.
Options are 'VeryRough', 'Rough', 'MediumRough', 'MediumSmooth', 'Smooth', and 'VerySmooth'
@param thickness [Double] thickness of the new material layer in meters @param conductivity [Double] thermal conductivity of new material layer in W/m*K @param density [Double] density of the new material layer in kg/m^3 @param specific_heat [Double] specific heat of the new material layer in J/kg*K @param thermal_absorptance [Double] target thermal absorptance @param solar_absorptance [Double] target solar absorptance @param visible_absorptance [Double] target visible absorptance @return [OpenStudio::Model::StandardOpaqueMaterial] The new material layer, a OpenStudio StandardOpaqueMaterial object
# File lib/openstudio-standards/constructions/modify.rb, line 22 def self.construction_add_new_opaque_material(construction, layer_index: 0, name: nil, roughness: nil, thickness: nil, conductivity: nil, density: nil, specific_heat: nil, thermal_absorptance: nil, solar_absorptance: nil, visible_absorptance: nil) # make new material new_material = OpenStudio::Model::StandardOpaqueMaterial.new(construction.model) if name.nil? new_material.setName("#{construction.name} New Material") else new_material.setName(name) end # set requested material properties new_material.setRoughness(roughness) unless roughness.nil? new_material.setThickness(thickness) unless thickness.nil? new_material.setConductivity(conductivity) unless conductivity.nil? new_material.setDensity(density) unless density.nil? new_material.setSpecificHeat(specific_heat) unless specific_heat.nil? new_material.setThermalAbsorptance(thermal_absorptance) unless thermal_absorptance.nil? new_material.setSolarAbsorptance(solar_absorptance) unless solar_absorptance.nil? new_material.setVisibleAbsorptance(visible_absorptance) unless visible_absorptance.nil? # add material to construction construction.insertLayer(layer_index, new_material) return new_material end
This will create a deep copy of the construction, meaning it will clone and create new material objects as well
@param construction [OpenStudio::Model::Construction] OpenStudio Construction object object @return [OpenStudio::Model::Construction] New OpenStudio Construction object
# File lib/openstudio-standards/constructions/create.rb, line 11 def self.construction_deep_copy(construction) new_construction = construction.clone.to_Construction.get (0..new_construction.layers.length - 1).each do |layer_number| cloned_layer = new_construction.getLayer(layer_number).clone.to_Material.get new_construction.setLayer(layer_number, cloned_layer) end return new_construction end
Find and set the insulation layer for a layered construction
@param construction [OpenStudio::Model::Construction] OpenStudio Construction object @return [OpenStudio::Model::OpaqueMaterial] OpenStudio OpaqueMaterial representing the insulation layer
# File lib/openstudio-standards/constructions/modify.rb, line 62 def self.construction_find_and_set_insulation_layer(construction) # skip and return the insulation layer if already set return construction.insulation.get if construction.insulation.is_initialized # loop through construction layers to find insulation layer min_conductance = 100.0 insulation_material = nil construction.layers.each do |layer| # skip layers that aren't an OpaqueMaterial next unless layer.to_OpaqueMaterial.is_initialized material = layer.to_OpaqueMaterial.get material_conductance = OpenstudioStandards::Constructions::Materials.material_get_conductance(material) if material_conductance < min_conductance min_conductance = material_conductance insulation_material = material end end construction.setInsulation(insulation_material) unless insulation_material.nil? if construction.isOpaque && !construction.insulation.is_initialized OpenStudio.logFree(OpenStudio::Error, 'OpenstudioStandards::Constructions', "Unable to determine the insulation layer for construction #{construction.name.get}.") return nil end return construction.insulation.get end
Return the thermal conductance for an OpenStudio Construction object
@param construction [OpenStudio::Model::Construction] OpenStudio Construction object @param temperature [Double] Temperature in Celsius, used for gas or gas mixture thermal conductance @return [Double] thermal conductance in W/m^2*K
# File lib/openstudio-standards/constructions/information.rb, line 102 def self.construction_get_conductance(construction, temperature: 0.0) # check to see if it can be cast as a layered construction, otherwise error unless construction.to_LayeredConstruction.is_initialized OpenStudio.logFree(OpenStudio::Error, 'OpenstudioStandards::Constructions', "Unable to determine conductance for construction #{construction.name} because it is not a LayeredConstruction.") return nil end construction = construction.to_LayeredConstruction.get total = 0.0 construction.layers.each do |material| total += 1.0 / OpenstudioStandards::Constructions::Materials.material_get_conductance(material, temperature: temperature) end return 1.0 / total end
Returns the solar reflectance index of an exposed surface. On a scale of 0 to 100, standard black is 0, and standard white is 100. The calculation derived from ASTM E1980 assuming medium wind speed.
@param construction [OpenStudio::Model::Construction] OpenStudio Construction object @return [Double] The solar reflectance value
# File lib/openstudio-standards/constructions/information.rb, line 178 def self.construction_get_solar_reflectance_index(construction) exposed_material = construction.to_LayeredConstruction.get.getLayer(0) solar_absorptance = exposed_material.to_OpaqueMaterial.get.solarAbsorptance thermal_emissivity = exposed_material.to_OpaqueMaterial.get.thermalAbsorptance x = ((20.797 * solar_absorptance) - (0.603 * thermal_emissivity)) / ((9.5205 * thermal_emissivity) + 12.0) sri = 123.97 - (141.35 * x) + (9.6555 * x * x) return sri end
Get the total solar transmittance for a fenestration construction (SHGC)
@param construction [OpenStudio::Model::Construction] OpenStudio Construction object @return [Double] total solar transmittance, or 0.0 if not available
# File lib/openstudio-standards/constructions/information.rb, line 122 def self.construction_get_solar_transmittance(construction) tsol = nil if construction.isFenestration tsol = 1.0 construction.layers.each do |layer| # Use shgc for simple glazing tsol *= layer.to_SimpleGlazing.get.solarHeatGainCoefficient unless layer.to_SimpleGlazing.empty? # Use solar transmittance for standard glazing tsol *= layer.to_StandardGlazing.get.solarTransmittance unless layer.to_StandardGlazing.empty? end end if tsol.nil? OpenStudio.logFree(OpenStudio::Warn, 'OpenstudioStandards::Constructions', "Unable to determine total solar transmittance for construction #{construction.name} because it is not considered Fenestration in the model. Returning a total solar transmittance of 0.0.") tsol = 0.0 end return tsol end
Get the total visible transmittance for a fenestration construction
@param construction [OpenStudio::Model::Construction] OpenStudio Construction object @return [Double] total visible transmittance, or 0.0 if not available
# File lib/openstudio-standards/constructions/information.rb, line 146 def self.construction_get_visible_transmittance(construction) tvis = nil if construction.isFenestration tvis = 1.0 construction.layers.each do |layer| # Use visible transmittance for simple glazing if specified unless layer.to_SimpleGlazing.empty? val = layer.to_SimpleGlazing.get.visibleTransmittance tvis *= val.get unless val.empty? end # Use visible transmittance for standard glazing if specified unless layer.to_StandardGlazing.empty? val = layer.to_StandardGlazing.get.visibleTransmittanceatNormalIncidence tvis *= val.get unless val.empty? end end end if tvis.nil? OpenStudio.logFree(OpenStudio::Warn, 'OpenstudioStandards::Constructions', "Unable to determine total visible transmittance for construction #{construction.name} because it is not considered Fenestration in the model. Returning a total visible transmittance of 0.0.") tvis = 0.0 end return tvis end
report names of constructions in a construction set
@param default_construction_set [OpenStudio::Model::DefaultConstructionSet] OpenStudio DefaultConstructionSet object @return [Array<OpenStudio::Model::Construction>] Array
of OpenStudio Construction objects
# File lib/openstudio-standards/constructions/information.rb, line 261 def self.construction_set_get_constructions(default_construction_set) construction_array = [] # populate exterior surfaces if default_construction_set.defaultExteriorSurfaceConstructions.is_initialized default_surface_constructions = default_construction_set.defaultExteriorSurfaceConstructions.get construction_array << default_surface_constructions.floorConstruction.get if default_surface_constructions.floorConstruction.is_initialized construction_array << default_surface_constructions.wallConstruction.get if default_surface_constructions.wallConstruction.is_initialized construction_array << default_surface_constructions.roofCeilingConstruction.get if default_surface_constructions.roofCeilingConstruction.is_initialized end # populate interior surfaces if default_construction_set.defaultInteriorSurfaceConstructions.is_initialized default_surface_constructions = default_construction_set.defaultInteriorSurfaceConstructions.get construction_array << default_surface_constructions.floorConstruction.get if default_surface_constructions.floorConstruction.is_initialized construction_array << default_surface_constructions.wallConstruction.get if default_surface_constructions.wallConstruction.is_initialized construction_array << default_surface_constructions.roofCeilingConstruction.get if default_surface_constructions.roofCeilingConstruction.is_initialized end # populate ground surfaces if default_construction_set.defaultGroundContactSurfaceConstructions.is_initialized default_surface_constructions = default_construction_set.defaultGroundContactSurfaceConstructions.get construction_array << default_surface_constructions.floorConstruction.get if default_surface_constructions.floorConstruction.is_initialized construction_array << default_surface_constructions.wallConstruction.get if default_surface_constructions.wallConstruction.is_initialized construction_array << default_surface_constructions.roofCeilingConstruction.get if default_surface_constructions.roofCeilingConstruction.is_initialized end # populate exterior sub-surfaces if default_construction_set.defaultExteriorSubSurfaceConstructions.is_initialized default_subsurface_constructions = default_construction_set.defaultExteriorSubSurfaceConstructions.get construction_array << default_subsurface_constructions.fixedWindowConstruction.get if default_subsurface_constructions.fixedWindowConstruction.is_initialized construction_array << default_subsurface_constructions.operableWindowConstruction.get if default_subsurface_constructions.operableWindowConstruction.is_initialized construction_array << default_subsurface_constructions.doorConstruction.get if default_subsurface_constructions.doorConstruction.is_initialized construction_array << default_subsurface_constructions.glassDoorConstruction.get if default_subsurface_constructions.glassDoorConstruction.is_initialized construction_array << default_subsurface_constructions.overheadDoorConstruction.get if default_subsurface_constructions.overheadDoorConstruction.is_initialized construction_array << default_subsurface_constructions.skylightConstruction.get if default_subsurface_constructions.skylightConstruction.is_initialized construction_array << default_subsurface_constructions.tubularDaylightDomeConstruction.get if default_subsurface_constructions.tubularDaylightDomeConstruction.is_initialized construction_array << default_subsurface_constructions.tubularDaylightDiffuserConstruction.get if default_subsurface_constructions.tubularDaylightDiffuserConstruction.is_initialized end # populate interior sub-surfaces if default_construction_set.defaultInteriorSubSurfaceConstructions.is_initialized default_subsurface_constructions = default_construction_set.defaultInteriorSubSurfaceConstructions.get construction_array << default_subsurface_constructions.fixedWindowConstruction.get if default_subsurface_constructions.fixedWindowConstruction.is_initialized construction_array << default_subsurface_constructions.operableWindowConstruction.get if default_subsurface_constructions.operableWindowConstruction.is_initialized construction_array << default_subsurface_constructions.doorConstruction.get if default_subsurface_constructions.doorConstruction.is_initialized construction_array << default_subsurface_constructions.glassDoorConstruction.get if default_subsurface_constructions.glassDoorConstruction.is_initialized construction_array << default_subsurface_constructions.overheadDoorConstruction.get if default_subsurface_constructions.overheadDoorConstruction.is_initialized construction_array << default_subsurface_constructions.skylightConstruction.get if default_subsurface_constructions.skylightConstruction.is_initialized construction_array << default_subsurface_constructions.tubularDaylightDomeConstruction.get if default_subsurface_constructions.tubularDaylightDomeConstruction.is_initialized construction_array << default_subsurface_constructions.tubularDaylightDiffuserConstruction.get if default_subsurface_constructions.tubularDaylightDiffuserConstruction.is_initialized end # populate misc surfaces construction_array << default_construction_set.interiorPartitionConstruction.get if default_construction_set.interiorPartitionConstruction.is_initialized construction_array << default_construction_set.spaceShadingConstruction.get if default_construction_set.spaceShadingConstruction.is_initialized construction_array << default_construction_set.buildingShadingConstruction.get if default_construction_set.buildingShadingConstruction.is_initialized construction_array << default_construction_set.siteShadingConstruction.get if default_construction_set.siteShadingConstruction.is_initialized return construction_array end
Sets the U-value of a simple glazing construction to a specified value by modifying the SimpleGlazing material.
@param construction [OpenStudio::Model::Construction] OpenStudio Construction object that contains SimpleGlazing @param target_u_value_ip [Double] Target heat transfer coefficient (U-Value) (Btu/ft^2*hr*R) @param target_includes_interior_film_coefficients [Boolean] If true, subtracts off standard interior film coefficients
from the target heat transfer coefficient before modifying insulation thickness.
@param target_includes_exterior_film_coefficients [Boolean] If true, subtracts off standard exterior film coefficients
from the target heat transfer coefficient before modifying insulation thickness.
@return [Boolean] returns true if successful, false if not
# File lib/openstudio-standards/constructions/modify.rb, line 217 def self.construction_set_glazing_u_value(construction, target_u_value_ip, target_includes_interior_film_coefficients: true, target_includes_exterior_film_coefficients: true) # Skip layer-by-layer fenestration constructions unless OpenstudioStandards::Constructions.construction_simple_glazing?(construction) OpenStudio.logFree(OpenStudio::Warn, 'OpenstudioStandards::Construction', "The construction_set_glazing_u_value method can only set the u-value of simple glazing. #{construction.name} does not containg simple glazing.") return false end # Convert the target U-value to SI target_r_value_ip = 1.0 / target_u_value_ip.to_f target_u_value_si = OpenStudio.convert(target_u_value_ip, 'Btu/ft^2*hr*R', 'W/m^2*K').get target_r_value_si = 1.0 / target_u_value_si # Determine the R-value of the air films, if requested # In EnergyPlus, the U-factor input of the WindowMaterial:SimpleGlazingSystem # object includes the film coefficients (see IDD description, and I/O reference # guide) so the target_includes_interior_film_coefficients and target_includes_exterior_film_coefficients # variable values are changed to their opposite so if the target value includes a film # the target value is unchanged film_coeff_r_value_si = 0.0 film_coeff_r_value_si += OpenstudioStandards::Constructions.film_coefficients_r_value('ExteriorWindow', !target_includes_interior_film_coefficients, !target_includes_exterior_film_coefficients) film_coeff_u_value_si = 1.0 / film_coeff_r_value_si film_coeff_u_value_ip = OpenStudio.convert(film_coeff_u_value_si, 'W/m^2*K', 'Btu/ft^2*hr*R').get film_coeff_r_value_ip = 1.0 / film_coeff_u_value_ip # Determine the difference between the desired R-value # and the R-value of the and air films. # This is the desired R-value of the insulation. ins_r_value_si = target_r_value_si - film_coeff_r_value_si if ins_r_value_si <= 0.0 ins_r_value_si = 0.001 OpenStudio.logFree(OpenStudio::Warn, 'OpenstudioStandards::Construction', "Requested U-value of #{target_u_value_ip} Btu/ft^2*hr*R for #{construction.name} is too high given the film coefficients of U-#{film_coeff_u_value_ip.round(2)} Btu/ft^2*hr*R.") end ins_u_value_si = 1.0 / ins_r_value_si if ins_u_value_si > 7.0 OpenStudio.logFree(OpenStudio::Warn, 'OpenstudioStandards::Construction', "Requested U-value of #{target_u_value_ip} for #{construction.name} is too high given the film coefficients of U-#{film_coeff_u_value_ip.round(2)}; setting U-value to EnergyPlus limit of 7.0 W/m^2*K (1.23 Btu/ft^2*hr*R).") ins_u_value_si = 7.0 end ins_u_value_ip = OpenStudio.convert(ins_u_value_si, 'W/m^2*K', 'Btu/ft^2*hr*R').get # Set the U-value of the insulation layer glazing = construction.layers.first.to_SimpleGlazing.get starting_u_value_si = glazing.uFactor.round(2) staring_u_value_ip = OpenStudio.convert(starting_u_value_si, 'W/m^2*K', 'Btu/ft^2*hr*R').get OpenStudio.logFree(OpenStudio::Debug, 'OpenstudioStandards::Construction', "Construction #{construction.name} contains SimpleGlazing '#{glazing.name}' with starting u_factor #{starting_u_value_si.round(2)} 'W/m^2*K' = #{staring_u_value_ip.round(2)} 'Btu/ft^2*hr*R'. Changing to u_factor #{ins_u_value_si.round(2)} 'W/m^2*K' = #{ins_u_value_ip.round(2)} 'Btu/ft^2*hr*R'.") glazing.setUFactor(ins_u_value_si) return true end
Set the F-Factor of a slab to a specified value. Assumes an unheated, fully insulated slab, and modifies the insulation layer according to the values from 90.1-2004 Table A6.3 Assembly F-Factors for Slab-on-Grade Floors.
@param construction [OpenStudio::Model::Construction] OpenStudio Construction object @param target_f_factor_ip [Double] Target F-Factor (Btu/ft*h*R) @param insulation_layer_name [String] The name of the insulation layer in this construction @return [Boolean] returns true if successful, false if not
# File lib/openstudio-standards/constructions/modify.rb, line 301 def self.construction_set_slab_f_factor(construction, target_f_factor_ip, insulation_layer_name: nil) # Regression from table A6.3 unheated, fully insulated slab r_value_ip = 1.0248 * (target_f_factor_ip**-2.186) u_value_ip = 1.0 / r_value_ip # Set the insulation U-value OpenstudioStandards::Constructions.construction_set_u_value(construction, u_value_ip, insulation_layer_name: insulation_layer_name, intended_surface_type: 'GroundContactFloor', target_includes_interior_film_coefficients: true, target_includes_exterior_film_coefficients: true) # Modify the construction name construction.setName("#{construction.name} F-#{target_f_factor_ip.round(3)}") return true end
set construction surface properties
@param construction [OpenStudio::Model::Construction] OpenStudio Construction object @param roughness [String] surface roughness @param thermal_absorptance [Double] target thermal absorptance @param solar_absorptance [Double] target solar absorptance @param visible_absorptance [Double] target visible absorptance @return [OpenStudio::Model::OpaqueMaterial] OpenStudio OpaqueMaterial object
# File lib/openstudio-standards/constructions/modify.rb, line 277 def self.construction_set_surface_properties(construction, roughness: nil, thermal_absorptance: nil, solar_absorptance: nil, visible_absorptance: nil) surface_material = construction.to_LayeredConstruction.get.getLayer(0) new_material = OpenstudioStandards::Constructions::Materials.opaque_material_set_surface_properties(surface_material, roughness: roughness, thermal_absorptance: thermal_absorptance, solar_absorptance: solar_absorptance, visible_absorptance: visible_absorptance) return new_material end
Set the surface specific F-factor parameters of a construction. This method only assumes one floor per space when calculating perimeter and area
@param construction [OpenStudio::Model::FFactorGroundFloorConstruction] OpenStudio F-factor Construction object @param target_f_factor_ip [Float] Target F-Factor (Btu/ft*h*R) @param surface [OpenStudio::Model::Surface] OpenStudio Surface object @return [Boolean] returns true if successful, false if not
# File lib/openstudio-standards/constructions/modify.rb, line 326 def self.construction_set_surface_slab_f_factor(construction, target_f_factor_ip, surface) # Get space associated with surface space = surface.space.get # Find this space's exposed floor area and perimeter. perimeter = OpenstudioStandards::Geometry.space_get_f_floor_perimeter(space) area = OpenstudioStandards::Geometry.space_get_f_floor_area(space) if area.zero? OpenStudio.logFree(OpenStudio::Error, 'OpenstudioStandards::Construction', "Area for #{surface.name} was calculated to be 0 m2, slab f-factor cannot be set.") return false end # Change construction name construction.setName("#{construction.name}_#{surface.name}_#{target_f_factor_ip}") # Set properties f_factor_si = target_f_factor_ip * OpenStudio.convert(1.0, 'Btu/ft*h*R', 'W/m*K').get construction.setFFactor(f_factor_si) construction.setArea(area) construction.setPerimeterExposed(perimeter) # Set surface outside boundary condition surface.setOutsideBoundaryCondition('GroundFCfactorMethod') return true end
Set the surface specific C-factor parameters of a construction
@param construction [OpenStudio::Model::CFactorUndergroundWallConstruction] OpenStudio C-factor Construction object @param target_c_factor_ip [Float] Target C-Factor (Btu/ft^2*h*R) @param surface [OpenStudio::Model::Surface] OpenStudio surface object @return [Boolean] returns true if successful, false if not
# File lib/openstudio-standards/constructions/modify.rb, line 387 def self.construction_set_surface_underground_wall_c_factor(construction, target_c_factor_ip, surface) # Get space associated with surface space = surface.space.get # Get height of the first below grade wall in this space. below_grade_wall_height = OpenstudioStandards::Geometry.space_get_below_grade_wall_height(space) if below_grade_wall_height.zero? OpenStudio.logFree(OpenStudio::Error, 'OpenstudioStandards::Construction', "Below grade wall height for #{surface.name} was calculated to be 0 m2, below grade wall c-factor cannot be set.") return false end # Change construction name construction.setName("#{construction.name}_#{surface.name}_#{target_c_factor_ip}") # Set properties c_factor_si = target_c_factor_ip * OpenStudio.convert(1.0, 'Btu/ft^2*h*R', 'W/m^2*K').get construction.setCFactor(c_factor_si) construction.setHeight(below_grade_wall_height) # Set surface outside boundary condition surface.setOutsideBoundaryCondition('GroundFCfactorMethod') end
Sets the heat transfer coefficient (U-value) of a construction to a specified value by modifying the thickness of the insulation layer.
@param construction [OpenStudio::Model::Construction] OpenStudio Construction object @param target_u_value_ip [Double] Target heat transfer coefficient (U-Value) (Btu/ft^2*hr*R) @param insulation_layer_name [String] The insulation layer in this construction. If none provided, the method will attempt to determine the insulation layer. @param intended_surface_type [String] Intended surface type, used for determining film coefficients.
Valid choices: 'AtticFloor', 'AtticWall', 'AtticRoof', 'DemisingFloor', 'InteriorFloor', 'InteriorCeiling', 'DemisingWall', 'InteriorWall', 'InteriorPartition', 'InteriorWindow', 'InteriorDoor', 'DemisingRoof', 'ExteriorRoof', 'Skylight', 'TubularDaylightDome', 'TubularDaylightDiffuser', 'ExteriorFloor', 'ExteriorWall', 'ExteriorWindow', 'ExteriorDoor', 'GlassDoor', 'OverheadDoor', 'GroundContactFloor', 'GroundContactWall', 'GroundContactRoof'
@param target_includes_interior_film_coefficients [Boolean] If true, subtracts off standard interior film coefficients
from the target heat transfer coefficient before modifying insulation thickness.
@param target_includes_exterior_film_coefficients [Boolean] If true, subtracts off standard exterior film coefficients
from the target heat transfer coefficient before modifying insulation thickness.
@return [Boolean] returns true if successful, false if not
# File lib/openstudio-standards/constructions/modify.rb, line 106 def self.construction_set_u_value(construction, target_u_value_ip, insulation_layer_name: nil, intended_surface_type: 'ExteriorWall', target_includes_interior_film_coefficients: true, target_includes_exterior_film_coefficients: true) # Skip layer-by-layer fenestration constructions if construction.isFenestration OpenStudio.logFree(OpenStudio::Warn, 'OpenstudioStandards::Constructions', "Can only set the u-value of opaque constructions or simple glazing. #{construction.name} is not opaque or simple glazing.") return false end # Make sure an insulation layer was specified if insulation_layer_name.nil? && (target_u_value_ip.abs < 0.01) # Do nothing if the construction already doesn't have an insulation layer elsif insulation_layer_name.nil? insulation_layer_name = OpenstudioStandards::Constructions.construction_find_and_set_insulation_layer(construction).name.get end # Remove the insulation layer if the specified U-value is zero. if target_u_value_ip.abs < 0.01 layer_index = 0 construction.layers.each do |layer| break if layer.name.get == insulation_layer_name layer_index += 1 end construction.eraseLayer(layer_index) return true end min_r_value_si = OpenstudioStandards::Constructions.film_coefficients_r_value(intended_surface_type, target_includes_interior_film_coefficients, target_includes_exterior_film_coefficients) max_u_value_si = 1.0 / min_r_value_si max_u_value_ip = OpenStudio.convert(max_u_value_si, 'W/m^2*K', 'Btu/ft^2*hr*R').get if target_u_value_ip >= max_u_value_ip target_u_value_ip = 1.0 / OpenStudio.convert(min_r_value_si + 0.001, 'm^2*K/W', 'ft^2*hr*R/Btu').get OpenStudio.logFree(OpenStudio::Warn, 'OpenstudioStandards::Constructions', "Requested U-value of #{target_u_value_ip} for #{construction.name} is greater than the sum of the inside and outside resistance, and the max U-value (6.636 SI) is used instead.") end # Convert the target U-value to SI target_r_value_ip = 1.0 / target_u_value_ip.to_f target_u_value_si = OpenStudio.convert(target_u_value_ip, 'Btu/ft^2*hr*R', 'W/m^2*K').get target_r_value_si = 1.0 / target_u_value_si OpenStudio.logFree(OpenStudio::Debug, 'OpenstudioStandards::Constructions', "Setting U-Value for #{construction.name} to #{target_u_value_si.round(3)} W/m^2*K or #{target_u_value_ip.round(3)} 'Btu/ft^2*hr*R', which is an R-value of #{target_r_value_si.round(3)} m^2*K/W or #{target_r_value_ip.round(3)} 'ft^2*hr*R/Btu'.") # Determine the R-value of the non-insulation layers other_layer_r_value_si = 0.0 construction.layers.each do |layer| next if layer.to_OpaqueMaterial.empty? next if layer.name.get == insulation_layer_name other_layer_r_value_si += layer.to_OpaqueMaterial.get.thermalResistance end # Determine the R-value of the air films, if requested other_layer_r_value_si += OpenstudioStandards::Constructions.film_coefficients_r_value(intended_surface_type, target_includes_interior_film_coefficients, target_includes_exterior_film_coefficients) # Determine the difference between the desired R-value # and the R-value of the non-insulation layers and air films. # This is the desired R-value of the insulation. ins_r_value_si = target_r_value_si - other_layer_r_value_si # Set the R-value of the insulation layer construction.layers.each_with_index do |layer, l| next unless layer.name.get == insulation_layer_name # Remove insulation layer if requested R-value is lower than sum of non-insulation materials if ins_r_value_si <= 0.0 OpenStudio.logFree(OpenStudio::Warn, 'OpenstudioStandards::Construction', "Requested U-value of #{target_u_value_ip} for #{construction.name} is too low given the other materials in the construction; insulation layer will be removed.") construction.eraseLayer(l) # Set the target R-value to the sum of other layers to make name match properties target_r_value_ip = OpenStudio.convert(other_layer_r_value_si, 'm^2*K/W', 'ft^2*hr*R/Btu').get break # Don't modify the insulation layer since it has been removed end # Modify the insulation layer ins_r_value_ip = OpenStudio.convert(ins_r_value_si, 'm^2*K/W', 'ft^2*h*R/Btu').get if layer.to_StandardOpaqueMaterial.is_initialized layer = layer.to_StandardOpaqueMaterial.get layer.setThickness(ins_r_value_si * layer.conductivity) layer.setName("#{layer.name} R-#{ins_r_value_ip.round(2)}") break # Stop looking for the insulation layer once found elsif layer.to_MasslessOpaqueMaterial.is_initialized layer = layer.to_MasslessOpaqueMaterial.get layer.setThermalResistance(ins_r_value_si) layer.setName("#{layer.name} R-#{ins_r_value_ip.round(2)}") break # Stop looking for the insulation layer once found elsif layer.to_AirGap.is_initialized layer = layer.to_AirGap.get target_thickness = ins_r_value_si * layer.thermalConductivity layer.setThickness(target_thickness) layer.setName("#{layer.name} R-#{ins_r_value_ip.round(2)}") break # Stop looking for the insulation layer once found end end # Modify the construction name construction.setName("#{construction.name} R-#{target_r_value_ip.round(2)}") return true end
Set the C-Factor of an underground wall to a specified value. Assumes continuous exterior insulation and modifies the insulation layer according to the values from 90.1-2004 Table A4.2 Assembly C-Factors for Below-Grade walls.
@param construction [OpenStudio::Model::Construction] OpenStudio Construction object @param target_c_factor_ip [Double] Target C-Factor (Btu/ft^2*h*R) @param insulation_layer_name [String] The name of the insulation layer in this construction @return [Boolean] returns true if successful, false if not
# File lib/openstudio-standards/constructions/modify.rb, line 363 def self.construction_set_underground_wall_c_factor(construction, target_c_factor_ip, insulation_layer_name: nil) # Regression from table A4.2 continuous exterior insulation r_value_ip = 0.775 * (target_c_factor_ip**-1.067) u_value_ip = 1.0 / r_value_ip # Set the insulation U-value OpenstudioStandards::Constructions.construction_set_u_value(construction, u_value_ip, insulation_layer_name: insulation_layer_name, intended_surface_type: 'GroundContactWall', target_includes_interior_film_coefficients: true, target_includes_exterior_film_coefficients: true) # Modify the construction name construction.setName("#{construction.name} C-#{target_c_factor_ip.round(3)}") return true end
Determines if the construction is a simple glazing construction, as indicated by having a single layer of type SimpleGlazing.
@param construction [OpenStudio::Model::Construction] OpenStudio Construction object @return [Boolean] returns true if it is a simple glazing, false if not
# File lib/openstudio-standards/constructions/information.rb, line 81 def self.construction_simple_glazing?(construction) # Not simple if more than 1 layer if construction.layers.length > 1 return false end # Not simple unless the layer is a SimpleGlazing material # if construction.layers.first.to_SimpleGlazing.empty? if construction.layers.first.to_SimpleGlazing.empty? return false end # If here, must be simple glazing return true end
Gives the total R-value of the interior and exterior (if applicable) film coefficients for a particular type of surface. @ref [References::ASHRAE9012010] A9.4.1 Air Films
@param intended_surface_type [String]
Valid choices: 'AtticFloor', 'AtticWall', 'AtticRoof', 'DemisingFloor', 'InteriorFloor', 'InteriorCeiling', 'DemisingWall', 'InteriorWall', 'InteriorPartition', 'InteriorWindow', 'InteriorDoor', 'DemisingRoof', 'ExteriorRoof', 'Skylight', 'TubularDaylightDome', 'TubularDaylightDiffuser', 'ExteriorFloor', 'ExteriorWall', 'ExteriorWindow', 'ExteriorDoor', 'GlassDoor', 'OverheadDoor', 'GroundContactFloor', 'GroundContactWall', 'GroundContactRoof'
@param int_film [Boolean] if true, interior film coefficient will be included in result @param ext_film [Boolean] if true, exterior film coefficient will be included in result @return [Double] Returns the R-Value of the film coefficients [m^2*K/W]
# File lib/openstudio-standards/constructions/information.rb, line 19 def self.film_coefficients_r_value(intended_surface_type, int_film, ext_film) # Return zero if both interior and exterior are false return 0.0 if !int_film && !ext_film # Film values from 90.1-2010 A9.4.1 Air Films film_ext_surf_r_ip = 0.17 film_semi_ext_surf_r_ip = 0.46 film_int_surf_ht_flow_up_r_ip = 0.61 film_int_surf_ht_flow_dwn_r_ip = 0.92 fil_int_surf_vertical_r_ip = 0.68 film_ext_surf_r_si = OpenStudio.convert(film_ext_surf_r_ip, 'ft^2*hr*R/Btu', 'm^2*K/W').get film_semi_ext_surf_r_si = OpenStudio.convert(film_semi_ext_surf_r_ip, 'ft^2*hr*R/Btu', 'm^2*K/W').get film_int_surf_ht_flow_up_r_si = OpenStudio.convert(film_int_surf_ht_flow_up_r_ip, 'ft^2*hr*R/Btu', 'm^2*K/W').get film_int_surf_ht_flow_dwn_r_si = OpenStudio.convert(film_int_surf_ht_flow_dwn_r_ip, 'ft^2*hr*R/Btu', 'm^2*K/W').get fil_int_surf_vertical_r_si = OpenStudio.convert(fil_int_surf_vertical_r_ip, 'ft^2*hr*R/Btu', 'm^2*K/W').get film_r_si = 0.0 case intended_surface_type when 'AtticFloor' film_r_si += film_int_surf_ht_flow_up_r_si if ext_film # Outside film_r_si += film_semi_ext_surf_r_si if int_film # Inside @todo: this is only true if the attic is ventilated, interior film should be used otheriwse when 'AtticWall', 'AtticRoof' film_r_si += film_ext_surf_r_si if ext_film # Outside film_r_si += film_semi_ext_surf_r_si if int_film # Inside @todo: this is only true if the attic is ventilated, interior film should be used otherwise when 'DemisingFloor', 'InteriorFloor' film_r_si += film_int_surf_ht_flow_up_r_si if ext_film # Outside film_r_si += film_int_surf_ht_flow_dwn_r_si if int_film # Inside when 'InteriorCeiling' film_r_si += film_int_surf_ht_flow_dwn_r_si if ext_film # Outside film_r_si += film_int_surf_ht_flow_up_r_si if int_film # Inside when 'DemisingWall', 'InteriorWall', 'InteriorPartition', 'InteriorWindow', 'InteriorDoor' film_r_si += fil_int_surf_vertical_r_si if ext_film # Outside film_r_si += fil_int_surf_vertical_r_si if int_film # Inside when 'DemisingRoof', 'ExteriorRoof', 'Skylight', 'TubularDaylightDome', 'TubularDaylightDiffuser' film_r_si += film_ext_surf_r_si if ext_film # Outside film_r_si += film_int_surf_ht_flow_up_r_si if int_film # Inside when 'ExteriorFloor' film_r_si += film_ext_surf_r_si if ext_film # Outside film_r_si += film_int_surf_ht_flow_dwn_r_si if int_film # Inside when 'ExteriorWall', 'ExteriorWindow', 'ExteriorDoor', 'GlassDoor', 'OverheadDoor' film_r_si += film_ext_surf_r_si if ext_film # Outside film_r_si += fil_int_surf_vertical_r_si if int_film # Inside when 'GroundContactFloor' film_r_si += film_int_surf_ht_flow_dwn_r_si if int_film # Inside when 'GroundContactWall' film_r_si += fil_int_surf_vertical_r_si if int_film # Inside when 'GroundContactRoof' film_r_si += film_int_surf_ht_flow_up_r_si if int_film # Inside end return film_r_si end
Return the existing adiabatic floor construction, or create one if absent.
@param model [OpenStudio::Model::Model] OpenStudio model object @return [OpenStudio::Model::Construction] OpenStudio Construction object
# File lib/openstudio-standards/constructions/create.rb, line 24 def self.model_get_adiabatic_floor_construction(model) adiabatic_construction_name = 'Adiabatic floor construction' # Check if adiabatic floor construction already exists in the model adiabatic_construct_exists = model.getConstructionByName(adiabatic_construction_name).is_initialized # Check to see if adiabatic construction has been constructed. If so, return it. Else, construct it. return model.getConstructionByName(adiabatic_construction_name).get if adiabatic_construct_exists # Assign construction to adiabatic construction cp02_carpet_pad = OpenStudio::Model::MasslessOpaqueMaterial.new(model) cp02_carpet_pad.setName('CP02 CARPET PAD') cp02_carpet_pad.setRoughness('VeryRough') cp02_carpet_pad.setThermalResistance(0.21648) cp02_carpet_pad.setThermalAbsorptance(0.9) cp02_carpet_pad.setSolarAbsorptance(0.7) cp02_carpet_pad.setVisibleAbsorptance(0.8) normalweight_concrete_floor = OpenStudio::Model::StandardOpaqueMaterial.new(model) normalweight_concrete_floor.setName('100mm Normalweight concrete floor') normalweight_concrete_floor.setRoughness('MediumSmooth') normalweight_concrete_floor.setThickness(0.1016) normalweight_concrete_floor.setThermalConductivity(2.31) normalweight_concrete_floor.setDensity(2322) normalweight_concrete_floor.setSpecificHeat(832) nonres_floor_insulation = OpenStudio::Model::MasslessOpaqueMaterial.new(model) nonres_floor_insulation.setName('Nonres_Floor_Insulation') nonres_floor_insulation.setRoughness('MediumSmooth') nonres_floor_insulation.setThermalResistance(2.88291975297193) nonres_floor_insulation.setThermalAbsorptance(0.9) nonres_floor_insulation.setSolarAbsorptance(0.7) nonres_floor_insulation.setVisibleAbsorptance(0.7) floor_adiabatic_construction = OpenStudio::Model::Construction.new(model) floor_adiabatic_construction.setName(adiabatic_construction_name) floor_layers = OpenStudio::Model::MaterialVector.new floor_layers << cp02_carpet_pad floor_layers << normalweight_concrete_floor floor_layers << nonres_floor_insulation floor_adiabatic_construction.setLayers(floor_layers) return floor_adiabatic_construction end
Return the existing adiabatic wall construction, or create one if absent.
@param model [OpenStudio::Model::Model] OpenStudio model object @return [OpenStudio::Model::Construction] OpenStudio Construction object
# File lib/openstudio-standards/constructions/create.rb, line 73 def self.model_get_adiabatic_wall_construction(model) adiabatic_construction_name = 'Adiabatic wall construction' # Check if adiabatic wall construction already exists in the model adiabatic_construct_exists = model.getConstructionByName(adiabatic_construction_name).is_initialized # Check to see if adiabatic construction has been constructed. If so, return it. Else, construct it. return model.getConstructionByName(adiabatic_construction_name).get if adiabatic_construct_exists g01_13mm_gypsum_board = OpenStudio::Model::StandardOpaqueMaterial.new(model) g01_13mm_gypsum_board.setName('G01 13mm gypsum board') g01_13mm_gypsum_board.setRoughness('Smooth') g01_13mm_gypsum_board.setThickness(0.0127) g01_13mm_gypsum_board.setThermalConductivity(0.1600) g01_13mm_gypsum_board.setDensity(800) g01_13mm_gypsum_board.setSpecificHeat(1090) g01_13mm_gypsum_board.setThermalAbsorptance(0.9) g01_13mm_gypsum_board.setSolarAbsorptance(0.7) g01_13mm_gypsum_board.setVisibleAbsorptance(0.5) wall_adiabatic_construction = OpenStudio::Model::Construction.new(model) wall_adiabatic_construction.setName(adiabatic_construction_name) wall_layers = OpenStudio::Model::MaterialVector.new wall_layers << g01_13mm_gypsum_board wall_layers << g01_13mm_gypsum_board wall_adiabatic_construction.setLayers(wall_layers) return wall_adiabatic_construction end
Get a unique list of constructions with a given boundary condition and surface type. Pulls from both default construction sets and hard-assigned constructions.
@param model [OpenStudio::Model::Model] OpenStudio model object @param boundary_condition [String] Surface boundary condition. Valid options are:
Adiabatic Surface Outdoors Ground
@param surface_type [String] Surface type to lookup. Valid options are:
AtticFloor AtticWall AtticRoof DemisingFloor DemisingWall DemisingRoof ExteriorFloor ExteriorWall ExteriorRoof ExteriorWindow ExteriorDoor GlassDoor GroundContactFloor GroundContactWall GroundContactRoof InteriorFloor InteriorWall InteriorCeiling InteriorPartition InteriorWindow InteriorDoor OverheadDoor Skylight TubularDaylightDome TubularDaylightDiffuser
return [Array<OpenStudio::Model::ConstructionBase>] An array of all constructions matching the given boundary condition and surface type
# File lib/openstudio-standards/constructions/information.rb, line 358 def self.model_get_constructions(model, boundary_condition, surface_type) constructions = [] # From default construction sets model.getDefaultConstructionSets.sort.each do |const_set| ext_surfs = const_set.defaultExteriorSurfaceConstructions int_surfs = const_set.defaultInteriorSurfaceConstructions gnd_surfs = const_set.defaultGroundContactSurfaceConstructions ext_subsurfs = const_set.defaultExteriorSubSurfaceConstructions int_subsurfs = const_set.defaultInteriorSubSurfaceConstructions # Can't handle incomplete construction sets if ext_surfs.empty? || int_surfs.empty? || gnd_surfs.empty? || ext_subsurfs.empty? || int_subsurfs.empty? OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Space', "Default construction set #{const_set.name} is incomplete; constructions from this set will not be reported.") next end ext_surfs = ext_surfs.get int_surfs = int_surfs.get gnd_surfs = gnd_surfs.get ext_subsurfs = ext_subsurfs.get int_subsurfs = int_subsurfs.get case surface_type # Exterior Surfaces when 'ExteriorWall', 'AtticWall' constructions << ext_surfs.wallConstruction when 'ExteriorFloor' constructions << ext_surfs.floorConstruction when 'ExteriorRoof', 'AtticRoof' constructions << ext_surfs.roofCeilingConstruction # Interior Surfaces when 'InteriorWall', 'DemisingWall', 'InteriorPartition' constructions << int_surfs.wallConstruction when 'InteriorFloor', 'AtticFloor', 'DemisingFloor' constructions << int_surfs.floorConstruction when 'InteriorCeiling', 'DemisingRoof' constructions << int_surfs.roofCeilingConstruction # Ground Contact Surfaces when 'GroundContactWall' constructions << gnd_surfs.wallConstruction when 'GroundContactFloor' constructions << gnd_surfs.floorConstruction when 'GroundContactRoof' constructions << gnd_surfs.roofCeilingConstruction # Exterior SubSurfaces when 'ExteriorWindow' constructions << ext_subsurfs.fixedWindowConstruction constructions << ext_subsurfs.operableWindowConstruction when 'ExteriorDoor' constructions << ext_subsurfs.doorConstruction when 'GlassDoor' constructions << ext_subsurfs.glassDoorConstruction when 'OverheadDoor' constructions << ext_subsurfs.overheadDoorConstruction when 'Skylight' constructions << ext_subsurfs.skylightConstruction when 'TubularDaylightDome' constructions << ext_subsurfs.tubularDaylightDomeConstruction when 'TubularDaylightDiffuser' constructions << ext_subsurfs.tubularDaylightDiffuserConstruction # Interior SubSurfaces when 'InteriorWindow' constructions << int_subsurfs.fixedWindowConstruction constructions << int_subsurfs.operableWindowConstruction when 'InteriorDoor' constructions << int_subsurfs.doorConstruction end end # Hard-assigned surfaces model.getSurfaces.sort.each do |surface| next unless surface.outsideBoundaryCondition == boundary_condition if surface.surfaceType == 'Floor' || surface.surfaceType == 'Wall' next unless surface_type.include?(surface.surfaceType) elsif surface.surfaceType == 'RoofCeiling' next unless surface_type.include?('Roof') || surface_type.include?('Ceiling') end constructions << surface.construction end # Hard-assigned subsurfaces model.getSubSurfaces.sort.each do |surface| next unless surface.outsideBoundaryCondition == boundary_condition case surface.subSurfaceType when 'FixedWindow', 'OperableWindow' next unless surface_type == 'ExteriorWindow' when 'Door' next unless surface_type.include?('Door') else next unless surface.subSurfaceType == surface_type end constructions << surface.construction end # Throw out the empty constructions all_constructions = [] constructions.uniq.each do |construction| next if construction.empty? all_constructions << construction.get end # return unique sorted ConstructionBases all_constructions = all_constructions.uniq.sort return all_constructions end
Determine the weighted average conductance for a set of planar surfaces (surfaces or sub surfaces)
@param surfaces [Array<OpenStudio::Model::PlanarSurface>] Array
of OpenStudio PlanarSurface objects @return [Double] thermal conductance in W/m^2*K, or nil if not available
# File lib/openstudio-standards/constructions/information.rb, line 196 def self.surfaces_get_conductance(surfaces) return nil if surfaces.empty? total_area = 0.0 temp = 0.0 surfaces.each do |surface| next unless surface.construction.is_initialized surface_construction = surface.model.getConstructionByName(surface.construction.get.name.to_s).get surface_conductance = OpenstudioStandards::Constructions.construction_get_conductance(surface_construction) temp += surface.netArea * surface_conductance total_area += surface.netArea end return nil if temp.zero? average_conductance = total_area.zero? ? 0.0 : temp / total_area return average_conductance end
Determine the weighted average solar transmittance for a set of planar surfaces (surfaces or sub surfaces)
@param surfaces [Array<OpenStudio::Model::PlanarSurface>] Array
of OpenStudio PlanarSurface objects @return [Double] total solar transmittance, or 1.0 if not available
# File lib/openstudio-standards/constructions/information.rb, line 219 def self.surfaces_get_solar_transmittance(surfaces) total_area = 0.0 temp = 0.0 surfaces.each do |surface| next unless surface.construction.is_initialized surface_construction = surface.model.getConstructionByName(surface.construction.get.name.to_s).get surface_shgc = OpenstudioStandards::Constructions.construction_get_solar_transmittance(surface_construction) temp += surface.netArea * surface_shgc total_area += surface.netArea end ave_shgc = total_area.zero? ? 1.0 : temp / total_area return ave_shgc end
Determine the weighted average visible transmittance for a set of planar surfaces (surfaces or sub surfaces)
@param surfaces [Array<OpenStudio::Model::PlanarSurface>] Array
of OpenStudio PlanarSurface objects @return [Double] total visible transmittance, or 1.0 if not available
# File lib/openstudio-standards/constructions/information.rb, line 238 def self.surfaces_get_visible_transmittance(surfaces) total_area = 0.0 temp = 0.0 surfaces.each do |surface| next unless surface.construction.is_initialized surface_construction = surface.model.getConstructionByName(surface.construction.get.name.to_s).get surface_tvis = OpenstudioStandards::Constructions.construction_get_visible_transmittance(surface_construction) temp += surface.netArea * surface_tvis total_area += surface.netArea end ave_tvis = total_area.zero? ? 1.0 : temp / total_area return ave_tvis end