Module: OpenstudioStandards::Constructions

Defined in:
lib/openstudio-standards/constructions/create.rb,
lib/openstudio-standards/constructions/modify.rb,
lib/openstudio-standards/constructions/information.rb,
lib/openstudio-standards/constructions/materials/modify.rb,
lib/openstudio-standards/constructions/materials/information.rb

Overview

The Constructions module provides methods create, modify, and get information about model Constructions

Defined Under Namespace

Modules: Materials

Create collapse

Modify collapse

Information collapse

Information:Construction collapse

Information:Surfaces collapse

Information:DefaultConstructionSet collapse

Information:Model collapse

Class Method Details

.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) ⇒ OpenStudio::Model::StandardOpaqueMaterial

add new material layer to a construction

Parameters:

  • construction (OpenStudio::Model::Construction)

    OpenStudio Construction object

  • layer_index (Integer) (defaults to: 0)

    the layer index, default is 0

  • name (String) (defaults to: nil)

    name of the new material layer

  • roughness (String) (defaults to: nil)

    surface roughness of the new material layer. Options are ‘VeryRough’, ‘Rough’, ‘MediumRough’, ‘MediumSmooth’, ‘Smooth’, and ‘VerySmooth’

  • thickness (Double) (defaults to: nil)

    thickness of the new material layer in meters

  • conductivity (Double) (defaults to: nil)

    thermal conductivity of new material layer in W/m*K

  • density (Double) (defaults to: nil)

    density of the new material layer in kg/m^3

  • specific_heat (Double) (defaults to: nil)

    specific heat of the new material layer in J/kg*K

  • thermal_absorptance (Double) (defaults to: nil)

    target thermal absorptance

  • solar_absorptance (Double) (defaults to: nil)

    target solar absorptance

  • visible_absorptance (Double) (defaults to: nil)

    target visible absorptance

Returns:

  • (OpenStudio::Model::StandardOpaqueMaterial)

    The new material layer, a OpenStudio StandardOpaqueMaterial object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 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

.construction_deep_copy(construction) ⇒ OpenStudio::Model::Construction

This will create a deep copy of the construction, meaning it will clone and create new material objects as well

Parameters:

  • construction (OpenStudio::Model::Construction)

    OpenStudio Construction object object

Returns:

  • (OpenStudio::Model::Construction)

    New OpenStudio Construction object



11
12
13
14
15
16
17
18
# 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

.construction_find_and_set_insulation_layer(construction) ⇒ OpenStudio::Model::OpaqueMaterial

Find and set the insulation layer for a layered construction

Parameters:

  • construction (OpenStudio::Model::Construction)

    OpenStudio Construction object

Returns:

  • (OpenStudio::Model::OpaqueMaterial)

    OpenStudio OpaqueMaterial representing the insulation layer



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# 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

.construction_get_conductance(construction, temperature: 0.0) ⇒ Double

Return the thermal conductance for an OpenStudio Construction object

Parameters:

  • construction (OpenStudio::Model::Construction)

    OpenStudio Construction object

  • temperature (Double) (defaults to: 0.0)

    Temperature in Celsius, used for gas or gas mixture thermal conductance

Returns:

  • (Double)

    thermal conductance in W/m^2*K



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# 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

.construction_get_solar_reflectance_index(construction) ⇒ Double

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.

Parameters:

  • construction (OpenStudio::Model::Construction)

    OpenStudio Construction object

Returns:

  • (Double)

    The solar reflectance value



178
179
180
181
182
183
184
185
186
# 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

.construction_get_solar_transmittance(construction) ⇒ Double

Get the total solar transmittance for a fenestration construction (SHGC)

Parameters:

  • construction (OpenStudio::Model::Construction)

    OpenStudio Construction object

Returns:

  • (Double)

    total solar transmittance, or 0.0 if not available



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# 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

.construction_get_visible_transmittance(construction) ⇒ Double

Get the total visible transmittance for a fenestration construction

Parameters:

  • construction (OpenStudio::Model::Construction)

    OpenStudio Construction object

Returns:

  • (Double)

    total visible transmittance, or 0.0 if not available



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# 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

.construction_set_get_constructions(default_construction_set) ⇒ Array<OpenStudio::Model::Construction>

report names of constructions in a construction set

Parameters:

  • default_construction_set (OpenStudio::Model::DefaultConstructionSet)

    OpenStudio DefaultConstructionSet object

Returns:

  • (Array<OpenStudio::Model::Construction>)

    Array of OpenStudio Construction objects



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# 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

.construction_set_glazing_u_value(construction, target_u_value_ip, target_includes_interior_film_coefficients: true, target_includes_exterior_film_coefficients: true) ⇒ Boolean

Sets the U-value of a simple glazing construction to a specified value by modifying the SimpleGlazing material.

Parameters:

  • construction (OpenStudio::Model::Construction)

    OpenStudio Construction object that contains SimpleGlazing

  • target_u_value_ip (Double)

    Target heat transfer coefficient (U-Value) (Btu/ft^2*hr*R)

  • target_includes_interior_film_coefficients (Boolean) (defaults to: true)

    If true, subtracts off standard interior film coefficients from the target heat transfer coefficient before modifying insulation thickness.

  • target_includes_exterior_film_coefficients (Boolean) (defaults to: true)

    If true, subtracts off standard exterior film coefficients from the target heat transfer coefficient before modifying insulation thickness.

Returns:

  • (Boolean)

    returns true if successful, false if not



217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# 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

.construction_set_slab_f_factor(construction, target_f_factor_ip, insulation_layer_name: nil) ⇒ Boolean

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.

Parameters:

  • construction (OpenStudio::Model::Construction)

    OpenStudio Construction object

  • target_f_factor_ip (Double)

    Target F-Factor (Btu/ft*h*R)

  • insulation_layer_name (String) (defaults to: nil)

    The name of the insulation layer in this construction

Returns:

  • (Boolean)

    returns true if successful, false if not



301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
# 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

.construction_set_surface_properties(construction, roughness: nil, thermal_absorptance: nil, solar_absorptance: nil, visible_absorptance: nil) ⇒ OpenStudio::Model::OpaqueMaterial

set construction surface properties

Parameters:

  • construction (OpenStudio::Model::Construction)

    OpenStudio Construction object

  • roughness (String) (defaults to: nil)

    surface roughness

  • thermal_absorptance (Double) (defaults to: nil)

    target thermal absorptance

  • solar_absorptance (Double) (defaults to: nil)

    target solar absorptance

  • visible_absorptance (Double) (defaults to: nil)

    target visible absorptance

Returns:

  • (OpenStudio::Model::OpaqueMaterial)

    OpenStudio OpaqueMaterial object



277
278
279
280
281
282
283
284
285
286
287
288
289
290
# 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

.construction_set_surface_slab_f_factor(construction, target_f_factor_ip, surface) ⇒ Boolean

Set the surface specific F-factor parameters of a construction. This method only assumes one floor per space when calculating perimeter and area

Parameters:

  • construction (OpenStudio::Model::FFactorGroundFloorConstruction)

    OpenStudio F-factor Construction object

  • target_f_factor_ip (Float)

    Target F-Factor (Btu/ft*h*R)

  • surface (OpenStudio::Model::Surface)

    OpenStudio Surface object

Returns:

  • (Boolean)

    returns true if successful, false if not



326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
# 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

.construction_set_surface_underground_wall_c_factor(construction, target_c_factor_ip, surface) ⇒ Boolean

Set the surface specific C-factor parameters of a construction

Parameters:

  • construction (OpenStudio::Model::CFactorUndergroundWallConstruction)

    OpenStudio C-factor Construction object

  • target_c_factor_ip (Float)

    Target C-Factor (Btu/ft^2*h*R)

  • surface (OpenStudio::Model::Surface)

    OpenStudio surface object

Returns:

  • (Boolean)

    returns true if successful, false if not



387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
# 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

.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) ⇒ Boolean

Sets the heat transfer coefficient (U-value) of a construction to a specified value by modifying the thickness of the insulation layer.

Parameters:

  • construction (OpenStudio::Model::Construction)

    OpenStudio Construction object

  • target_u_value_ip (Double)

    Target heat transfer coefficient (U-Value) (Btu/ft^2*hr*R)

  • insulation_layer_name (String) (defaults to: nil)

    The insulation layer in this construction. If none provided, the method will attempt to determine the insulation layer.

  • intended_surface_type (String) (defaults to: 'ExteriorWall')

    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’

  • target_includes_interior_film_coefficients (Boolean) (defaults to: true)

    If true, subtracts off standard interior film coefficients from the target heat transfer coefficient before modifying insulation thickness.

  • target_includes_exterior_film_coefficients (Boolean) (defaults to: true)

    If true, subtracts off standard exterior film coefficients from the target heat transfer coefficient before modifying insulation thickness.

Returns:

  • (Boolean)

    returns true if successful, false if not



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# 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

.construction_set_underground_wall_c_factor(construction, target_c_factor_ip, insulation_layer_name: nil) ⇒ Boolean

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.

Parameters:

  • construction (OpenStudio::Model::Construction)

    OpenStudio Construction object

  • target_c_factor_ip (Double)

    Target C-Factor (Btu/ft^2*h*R)

  • insulation_layer_name (String) (defaults to: nil)

    The name of the insulation layer in this construction

Returns:

  • (Boolean)

    returns true if successful, false if not



363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
# 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

.construction_simple_glazing?(construction) ⇒ Boolean

Determines if the construction is a simple glazing construction, as indicated by having a single layer of type SimpleGlazing.

Parameters:

  • construction (OpenStudio::Model::Construction)

    OpenStudio Construction object

Returns:

  • (Boolean)

    returns true if it is a simple glazing, false if not



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# 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

.film_coefficients_r_value(intended_surface_type, int_film, ext_film) ⇒ Double

Gives the total R-value of the interior and exterior (if applicable) film coefficients for a particular type of surface.

Parameters:

  • 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’

  • int_film (Boolean)

    if true, interior film coefficient will be included in result

  • ext_film (Boolean)

    if true, exterior film coefficient will be included in result

Returns:

  • (Double)

    Returns the R-Value of the film coefficients [m^2*K/W]



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# 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

.model_get_adiabatic_floor_construction(model) ⇒ OpenStudio::Model::Construction

Return the existing adiabatic floor construction, or create one if absent.

Parameters:

  • model (OpenStudio::Model::Model)

    OpenStudio model object

Returns:

  • (OpenStudio::Model::Construction)

    OpenStudio Construction object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# 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

.model_get_adiabatic_wall_construction(model) ⇒ OpenStudio::Model::Construction

Return the existing adiabatic wall construction, or create one if absent.

Parameters:

  • model (OpenStudio::Model::Model)

    OpenStudio model object

Returns:

  • (OpenStudio::Model::Construction)

    OpenStudio Construction object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# 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

.model_get_constructions(model, boundary_condition, surface_type) ⇒ Object

Get a unique list of constructions with a given boundary condition and surface type. Pulls from both default construction sets and hard-assigned constructions.

return [Array<OpenStudio::Model::ConstructionBase>] An array of all constructions matching the given boundary condition and surface type

Parameters:

  • model (OpenStudio::Model::Model)

    OpenStudio model object

  • boundary_condition (String)

    Surface boundary condition. Valid options are: Adiabatic Surface Outdoors Ground

  • 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



358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
# 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

.surfaces_get_conductance(surfaces) ⇒ Double

Determine the weighted average conductance for a set of planar surfaces (surfaces or sub surfaces)

Parameters:

  • surfaces (Array<OpenStudio::Model::PlanarSurface>)

    Array of OpenStudio PlanarSurface objects

Returns:

  • (Double)

    thermal conductance in W/m^2*K, or nil if not available



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# 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

.surfaces_get_solar_transmittance(surfaces) ⇒ Double

Determine the weighted average solar transmittance for a set of planar surfaces (surfaces or sub surfaces)

Parameters:

  • surfaces (Array<OpenStudio::Model::PlanarSurface>)

    Array of OpenStudio PlanarSurface objects

Returns:

  • (Double)

    total solar transmittance, or 1.0 if not available



219
220
221
222
223
224
225
226
227
228
229
230
231
232
# 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

.surfaces_get_visible_transmittance(surfaces) ⇒ Double

Determine the weighted average visible transmittance for a set of planar surfaces (surfaces or sub surfaces)

Parameters:

  • surfaces (Array<OpenStudio::Model::PlanarSurface>)

    Array of OpenStudio PlanarSurface objects

Returns:

  • (Double)

    total visible transmittance, or 1.0 if not available



238
239
240
241
242
243
244
245
246
247
248
249
250
251
# 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