Class: IncreaseInsulationRValueForRoofsByPercentage
- Inherits:
-
OpenStudio::Ruleset::ModelUserScript
- Object
- OpenStudio::Ruleset::ModelUserScript
- IncreaseInsulationRValueForRoofsByPercentage
- Defined in:
- lib/measures/IncreaseInsulationRValueForRoofsByPercentage/measure.rb
Overview
start the measure
Instance Method Summary collapse
-
#arguments(model) ⇒ Object
define the arguments that the user will input.
-
#name ⇒ Object
define the name that a user will see.
-
#neat_numbers(number, roundto = 2) ⇒ Object
short def to make numbers pretty (converts 4125001.25641 to 4,125,001.26 or 4,125,001).
-
#run(model, runner, user_arguments) ⇒ Object
define what happens when the measure is run.
-
#unit_helper(number, from_unit_string, to_unit_string) ⇒ Object
helper to make it easier to do unit conversions on the fly.
Instance Method Details
#arguments(model) ⇒ Object
define the arguments that the user will input
14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/measures/IncreaseInsulationRValueForRoofsByPercentage/measure.rb', line 14 def arguments(model) args = OpenStudio::Ruleset::OSArgumentVector.new # make an argument insulation R-value r_value = OpenStudio::Ruleset::OSArgument.makeDoubleArgument('r_value', true) r_value.setDisplayName('Percentage Increase of R-value for Roof Insulation.') r_value.setDefaultValue(30.0) args << r_value return args end |
#name ⇒ Object
define the name that a user will see
9 10 11 |
# File 'lib/measures/IncreaseInsulationRValueForRoofsByPercentage/measure.rb', line 9 def name return 'Increase R-value of Insulation for Roofs by a Specified Percentage.' end |
#neat_numbers(number, roundto = 2) ⇒ Object
short def to make numbers pretty (converts 4125001.25641 to 4,125,001.26 or 4,125,001). The definition be called through this measure
48 49 50 51 52 53 54 55 56 |
# File 'lib/measures/IncreaseInsulationRValueForRoofsByPercentage/measure.rb', line 48 def neat_numbers(number, roundto = 2) # round to 0 or 2) if roundto == 2 number = format '%.2f', number else number = number.round end # regex to add commas number.to_s.reverse.gsub(/([0-9]{3}(?=([0-9])))/, '\\1,').reverse end |
#run(model, runner, user_arguments) ⇒ Object
define what happens when the measure is run
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 71 72 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 102 103 104 105 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 207 208 209 210 211 212 213 214 215 216 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 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 |
# File 'lib/measures/IncreaseInsulationRValueForRoofsByPercentage/measure.rb', line 27 def run(model, runner, user_arguments) super(model, runner, user_arguments) # use the built-in error checking if !runner.validateUserArguments(arguments(model), user_arguments) return false end # assign the user inputs to variables r_value = runner.getDoubleArgumentValue('r_value', user_arguments) # set limit for minimum insulation. This is used to limit input and for inferring insulation layer in construction. min_expected_r_value_ip = 1 # ip units # check the R-value for reasonableness if r_value < -100 runner.registerError('Percentage increase less than -100% is not valid.') return false end # short def to make numbers pretty (converts 4125001.25641 to 4,125,001.26 or 4,125,001). The definition be called through this measure def neat_numbers(number, roundto = 2) # round to 0 or 2) if roundto == 2 number = format '%.2f', number else number = number.round end # regex to add commas number.to_s.reverse.gsub(/([0-9]{3}(?=([0-9])))/, '\\1,').reverse end # helper to make it easier to do unit conversions on the fly def unit_helper(number, from_unit_string, to_unit_string) converted_number = OpenStudio.convert(OpenStudio::Quantity.new(number, OpenStudio.createUnit(from_unit_string).get), OpenStudio.createUnit(to_unit_string).get).get.value end # create an array of roofs and find range of starting construction R-value (not just insulation layer) surfaces = model.getSurfaces exterior_surfaces = [] exterior_surface_constructions = [] exterior_surface_construction_names = [] roof_resistance = [] surfaces.each do |surface| if (surface.outsideBoundaryCondition == 'Outdoors') && (surface.surfaceType == 'RoofCeiling') exterior_surfaces << surface roof_const = surface.construction.get # only add construction if it hasn't been added yet if !exterior_surface_construction_names.include?(roof_const.name.to_s) exterior_surface_constructions << roof_const.to_Construction.get end exterior_surface_construction_names << roof_const.name.to_s roof_resistance << 1 / roof_const.thermalConductance.to_f end end # nothing will be done if there are no exterior surfaces if exterior_surfaces.empty? runner.registerAsNotApplicable('Model does not have any roofs.') return true end # report strings for initial condition initial_string = [] exterior_surface_constructions.uniq.each do |exterior_surface_construction| # unit conversion of roof insulation from SI units (M^2*K/W) to IP units (ft^2*h*R/Btu) initial_conductance_ip = unit_helper(1 / exterior_surface_construction.thermalConductance.to_f, 'm^2*K/W', 'ft^2*h*R/Btu') initial_string << "#{exterior_surface_construction.name} (R-#{(format '%.1f', initial_conductance_ip)})" end runner.registerInitialCondition("The building had #{initial_string.size} roof constructions: #{initial_string.sort.join(', ')}.") # hashes to track constructions and materials made by the measure, to avoid duplicates constructions_hash_old_new = {} constructions_hash_new_old = {} # used to get netArea of new construction and then cost objects of construction it replaced materials_hash = {} # array and counter for new constructions that are made, used for reporting final condition final_constructions_array = [] # loop through all constructions and materials used on roofs, edit and clone exterior_surface_constructions.each do |exterior_surface_construction| construction_layers = exterior_surface_construction.layers max_thermal_resistance_material = '' max_thermal_resistance_material_index = '' counter = 0 thermal_resistance_values = [] # loop through construction layers and infer insulation layer/material construction_layers.each do |construction_layer| construction_layer_r_value = construction_layer.to_OpaqueMaterial.get.thermalResistance if !thermal_resistance_values.empty? if construction_layer_r_value > thermal_resistance_values.max max_thermal_resistance_material = construction_layer max_thermal_resistance_material_index = counter end end thermal_resistance_values << construction_layer_r_value counter += 1 end if thermal_resistance_values.max <= unit_helper(min_expected_r_value_ip, 'ft^2*h*R/Btu', 'm^2*K/W') runner.registerWarning("Construction '#{exterior_surface_construction.name}' does not appear to have an insulation layer and was not altered.") else # clone the construction final_construction = exterior_surface_construction.clone(model) final_construction = final_construction.to_Construction.get final_construction.setName("#{exterior_surface_construction.name} adj roof insulation") final_constructions_array << final_construction # add construction object if it didnt exist to start with # push to hashes constructions_hash_old_new[exterior_surface_construction.name.to_s] = final_construction constructions_hash_new_old[final_construction] = exterior_surface_construction # push the object to hash key vs. name # find already cloned insulation material and link to construction target_material = max_thermal_resistance_material found_material = false materials_hash.each do |orig, new| if target_material.name.to_s == orig new_material = new materials_hash[max_thermal_resistance_material.name.to_s] = new_material final_construction.eraseLayer(max_thermal_resistance_material_index) final_construction.insertLayer(max_thermal_resistance_material_index, new_material) found_material = true end end # clone and edit insulation material and link to construction if found_material == false new_material = max_thermal_resistance_material.clone(model) new_material = new_material.to_OpaqueMaterial.get new_material.setName("#{max_thermal_resistance_material.name}_R-value #{r_value}% increase") materials_hash[max_thermal_resistance_material.name.to_s] = new_material final_construction.eraseLayer(max_thermal_resistance_material_index) final_construction.insertLayer(max_thermal_resistance_material_index, new_material) runner.registerInfo("For construction'#{final_construction.name}', material'#{new_material.name}' was altered.") # edit insulation material new_material_matt = new_material.to_Material if !new_material_matt.empty? starting_thickness = new_material_matt.get.thickness target_thickness = starting_thickness * (1 + r_value / 100) final_thickness = new_material_matt.get.setThickness(target_thickness) end new_material_massless = new_material.to_MasslessOpaqueMaterial if !new_material_massless.empty? starting_thermal_resistance = new_material_massless.get.thermalResistance final_thermal_resistance = new_material_massless.get.setThermalResistance(starting_thermal_resistance * (1 + r_value / 100)) end new_material_airgap = new_material.to_AirGap if !new_material_airgap.empty? starting_thermal_resistance = new_material_airgap.get.thermalResistance final_thermal_resistance = new_material_airgap.get.setThermalResistance(starting_thermal_resistance * (1 + r_value / 100)) end end end end # loop through construction sets used in the model default_construction_sets = model.getDefaultConstructionSets default_construction_sets.each do |default_construction_set| if default_construction_set.directUseCount > 0 default_surface_const_set = default_construction_set.defaultExteriorSurfaceConstructions if !default_surface_const_set.empty? starting_construction = default_surface_const_set.get.roofCeilingConstruction # creating new default construction set new_default_construction_set = default_construction_set.clone(model) new_default_construction_set = new_default_construction_set.to_DefaultConstructionSet.get new_default_construction_set.setName("#{default_construction_set.name} adj roof insulation") # create new surface set and link to construction set new_default_surface_const_set = default_surface_const_set.get.clone(model) new_default_surface_const_set = new_default_surface_const_set.to_DefaultSurfaceConstructions.get new_default_surface_const_set.setName("#{default_surface_const_set.get.name} adj roof insulation") new_default_construction_set.setDefaultExteriorSurfaceConstructions(new_default_surface_const_set) # use the hash to find the proper construction and link to new_default_surface_const_set target_const = new_default_surface_const_set.roofCeilingConstruction if !target_const.empty? target_const = target_const.get.name.to_s found_const_flag = false constructions_hash_old_new.each do |orig, new| if target_const == orig final_construction = new new_default_surface_const_set.setRoofCeilingConstruction(final_construction) found_const_flag = true end end if found_const_flag == false # this should never happen but is just an extra test in case something goes wrong with the measure code runner.registerWarning("Measure couldn't find the construction named '#{target_const}' in the exterior surface hash.") end end # swap all uses of the old construction set for the new construction_set_sources = default_construction_set.sources construction_set_sources.each do |construction_set_source| building_source = construction_set_source.to_Building # if statement for each type of object than can use a DefaultConstructionSet if !building_source.empty? building_source = building_source.get building_source.setDefaultConstructionSet(new_default_construction_set) end building_story_source = construction_set_source.to_BuildingStory if !building_story_source.empty? building_story_source = building_story_source.get building_story_source.setDefaultConstructionSet(new_default_construction_set) end space_type_source = construction_set_source.to_SpaceType if !space_type_source.empty? space_type_source = space_type_source.get space_type_source.setDefaultConstructionSet(new_default_construction_set) end space_source = construction_set_source.to_Space if !space_source.empty? space_source = space_source.get space_source.setDefaultConstructionSet(new_default_construction_set) end end end end end # link cloned and edited constructions for surfaces with hard assigned constructions exterior_surfaces.each do |exterior_surface| if !exterior_surface.isConstructionDefaulted && !exterior_surface.construction.empty? # use the hash to find the proper construction and link to surface target_const = exterior_surface.construction if !target_const.empty? target_const = target_const.get.name.to_s constructions_hash_old_new.each do |orig, new| if target_const == orig final_construction = new exterior_surface.setConstruction(final_construction) end end end end end # report strings for final condition final_string = [] # not all exterior roof constructions, but only new ones made. If roof didn't have insulation and was not altered we don't want to show it affected_area_si = 0 final_constructions_array.each do |final_construction| # unit conversion of roof insulation from SI units (M^2*K/W) to IP units (ft^2*h*R/Btu) final_conductance_ip = unit_helper(1 / final_construction.thermalConductance.to_f, 'm^2*K/W', 'ft^2*h*R/Btu') final_string << "#{final_construction.name} (R-#{(format '%.1f', final_conductance_ip)})" affected_area_si += final_construction.getNetArea end # add not applicable test if there were exterior roof constructions but non of them were altered (already enough insulation or doesn't look like insulated wall) if affected_area_si == 0 runner.registerAsNotApplicable('No roofs were altered.') return true # affected_area_ip = affected_area_si else # ip construction area for reporting affected_area_ip = unit_helper(affected_area_si, 'm^2', 'ft^2') end # report final condition runner.registerFinalCondition("The existing insulation for roofs was increased by #{r_value}%. This was applied to #{neat_numbers(affected_area_ip, 0)} (ft^2) across #{final_string.size} roof constructions: #{final_string.sort.join(', ')}.") return true end |
#unit_helper(number, from_unit_string, to_unit_string) ⇒ Object
helper to make it easier to do unit conversions on the fly
59 60 61 |
# File 'lib/measures/IncreaseInsulationRValueForRoofsByPercentage/measure.rb', line 59 def unit_helper(number, from_unit_string, to_unit_string) converted_number = OpenStudio.convert(OpenStudio::Quantity.new(number, OpenStudio.createUnit(from_unit_string).get), OpenStudio.createUnit(to_unit_string).get).get.value end |