openstudio-ee 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/lib/measures/IncreaseInsulationRValueForExteriorWallsByPercentage/LICENSE.md +27 -0
- data/lib/measures/IncreaseInsulationRValueForExteriorWallsByPercentage/README.md +32 -0
- data/lib/measures/IncreaseInsulationRValueForExteriorWallsByPercentage/README.md.erb +42 -0
- data/lib/measures/IncreaseInsulationRValueForExteriorWallsByPercentage/measure.rb +328 -0
- data/lib/measures/IncreaseInsulationRValueForExteriorWallsByPercentage/measure.xml +98 -0
- data/lib/measures/IncreaseInsulationRValueForRoofsByPercentage/LICENSE.md +27 -0
- data/lib/measures/IncreaseInsulationRValueForRoofsByPercentage/README.md +32 -0
- data/lib/measures/IncreaseInsulationRValueForRoofsByPercentage/README.md.erb +42 -0
- data/lib/measures/IncreaseInsulationRValueForRoofsByPercentage/measure.rb +328 -0
- data/lib/measures/IncreaseInsulationRValueForRoofsByPercentage/measure.xml +98 -0
- data/lib/openstudio/ee_measures/version.rb +1 -1
- metadata +13 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a07f9ea766569efdacd19a444e23fe54e73576187c1cd5aafaabcb0fd0c81f6
|
4
|
+
data.tar.gz: 7e2c9af297cb812c9dea02e5cb27aa2c15a89a7b620a520c69b20eaec08c593c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9bb2dca9010b26cf6685acdb16fcf2f77d859f76d40add6a3713a1f7e8ef5f6b130be0eb74506d4498b24fcf8f65697019085b9844f912de90f74ab6109c5311
|
7
|
+
data.tar.gz: c2d75bb0236504bb249255df518113dfc4512576729ab7ac03067da92a3d67c0cce38c53d278da732edeb09c2b3544d0771aac7af08304400696c2afaef14704
|
data/CHANGELOG.md
CHANGED
@@ -0,0 +1,27 @@
|
|
1
|
+
OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted
|
4
|
+
provided that the following conditions are met:
|
5
|
+
|
6
|
+
(1) Redistributions of source code must retain the above copyright notice, this list of conditions
|
7
|
+
and the following disclaimer.
|
8
|
+
|
9
|
+
(2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
10
|
+
and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
11
|
+
|
12
|
+
(3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse
|
13
|
+
or promote products derived from this software without specific prior written permission from the
|
14
|
+
respective party.
|
15
|
+
|
16
|
+
(4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other
|
17
|
+
derivative works may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar
|
18
|
+
designation without specific prior written permission from Alliance for Sustainable Energy, LLC.
|
19
|
+
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
21
|
+
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
22
|
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES GOVERNMENT,
|
23
|
+
OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
25
|
+
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
26
|
+
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
27
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
###### (Automatically generated documentation)
|
4
|
+
|
5
|
+
# Increase R-value of Insulation for Exterior Walls By a Specified Percentage
|
6
|
+
|
7
|
+
## Description
|
8
|
+
|
9
|
+
|
10
|
+
## Modeler Description
|
11
|
+
|
12
|
+
|
13
|
+
## Measure Type
|
14
|
+
ModelMeasure
|
15
|
+
|
16
|
+
## Taxonomy
|
17
|
+
|
18
|
+
|
19
|
+
## Arguments
|
20
|
+
|
21
|
+
|
22
|
+
### Percentage Increase of R-value for Exterior Wall Insulation.
|
23
|
+
|
24
|
+
**Name:** r_value,
|
25
|
+
**Type:** Double,
|
26
|
+
**Units:** ,
|
27
|
+
**Required:** true,
|
28
|
+
**Model Dependent:** false
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<%#= README.md.erb is used to auto-generate README.md. %>
|
2
|
+
<%#= To manually maintain README.md throw away README.md.erb and manually edit README.md %>
|
3
|
+
###### (Automatically generated documentation)
|
4
|
+
|
5
|
+
# <%= name %>
|
6
|
+
|
7
|
+
## Description
|
8
|
+
<%= description %>
|
9
|
+
|
10
|
+
## Modeler Description
|
11
|
+
<%= modelerDescription %>
|
12
|
+
|
13
|
+
## Measure Type
|
14
|
+
<%= measureType %>
|
15
|
+
|
16
|
+
## Taxonomy
|
17
|
+
<%= taxonomy %>
|
18
|
+
|
19
|
+
## Arguments
|
20
|
+
|
21
|
+
<% arguments.each do |argument| %>
|
22
|
+
### <%= argument[:display_name] %>
|
23
|
+
<%= argument[:description] %>
|
24
|
+
**Name:** <%= argument[:name] %>,
|
25
|
+
**Type:** <%= argument[:type] %>,
|
26
|
+
**Units:** <%= argument[:units] %>,
|
27
|
+
**Required:** <%= argument[:required] %>,
|
28
|
+
**Model Dependent:** <%= argument[:model_dependent] %>
|
29
|
+
<% end %>
|
30
|
+
|
31
|
+
<% if arguments.size == 0 %>
|
32
|
+
<%= "This measure does not have any user arguments" %>
|
33
|
+
<% end %>
|
34
|
+
|
35
|
+
<% if outputs.size > 0 %>
|
36
|
+
## Outputs
|
37
|
+
<% output_names = [] %>
|
38
|
+
<% outputs.each do |output| %>
|
39
|
+
<% output_names << output[:display_name] %>
|
40
|
+
<% end %>
|
41
|
+
<%= output_names.join(", ") %>
|
42
|
+
<% end %>
|
@@ -0,0 +1,328 @@
|
|
1
|
+
# *******************************************************************************
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
|
3
|
+
# All rights reserved.
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
#
|
10
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
#
|
14
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
15
|
+
# may be used to endorse or promote products derived from this software without
|
16
|
+
# specific prior written permission from the respective party.
|
17
|
+
#
|
18
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
19
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
20
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
21
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
24
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
25
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
26
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
27
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
28
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
29
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
30
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
31
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
32
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
33
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
# *******************************************************************************
|
35
|
+
|
36
|
+
# start the measure
|
37
|
+
class IncreaseInsulationRValueForExteriorWallsByPercentage < OpenStudio::Ruleset::ModelUserScript
|
38
|
+
# define the name that a user will see
|
39
|
+
def name
|
40
|
+
return 'Increase R-value of Insulation for Exterior Walls By a Specified Percentage'
|
41
|
+
end
|
42
|
+
|
43
|
+
# define the arguments that the user will input
|
44
|
+
def arguments(model)
|
45
|
+
args = OpenStudio::Ruleset::OSArgumentVector.new
|
46
|
+
|
47
|
+
# make an argument insulation R-value
|
48
|
+
r_value = OpenStudio::Ruleset::OSArgument.makeDoubleArgument('r_value', true)
|
49
|
+
r_value.setDisplayName('Percentage Increase of R-value for Exterior Wall Insulation.')
|
50
|
+
r_value.setDefaultValue(30.0)
|
51
|
+
args << r_value
|
52
|
+
|
53
|
+
return args
|
54
|
+
end
|
55
|
+
|
56
|
+
# define what happens when the measure is run
|
57
|
+
def run(model, runner, user_arguments)
|
58
|
+
super(model, runner, user_arguments)
|
59
|
+
|
60
|
+
# use the built-in error checking
|
61
|
+
if !runner.validateUserArguments(arguments(model), user_arguments)
|
62
|
+
return false
|
63
|
+
end
|
64
|
+
|
65
|
+
# assign the user inputs to variables
|
66
|
+
r_value = runner.getDoubleArgumentValue('r_value', user_arguments)
|
67
|
+
|
68
|
+
# set limit for minimum insulation. This is used to limit input and for inferring insulation layer in construction.
|
69
|
+
min_expected_r_value_ip = 1 # ip units
|
70
|
+
|
71
|
+
# check the R-value for reasonableness
|
72
|
+
if r_value < -100
|
73
|
+
runner.registerError('Percentage increase less than -100% is not valid.')
|
74
|
+
return false
|
75
|
+
end
|
76
|
+
|
77
|
+
# 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
|
78
|
+
def neat_numbers(number, roundto = 2) # round to 0 or 2)
|
79
|
+
if roundto == 2
|
80
|
+
number = format '%.2f', number
|
81
|
+
else
|
82
|
+
number = number.round
|
83
|
+
end
|
84
|
+
# regex to add commas
|
85
|
+
number.to_s.reverse.gsub(/([0-9]{3}(?=([0-9])))/, '\\1,').reverse
|
86
|
+
end
|
87
|
+
|
88
|
+
# helper to make it easier to do unit conversions on the fly
|
89
|
+
def unit_helper(number, from_unit_string, to_unit_string)
|
90
|
+
converted_number = OpenStudio.convert(OpenStudio::Quantity.new(number, OpenStudio.createUnit(from_unit_string).get), OpenStudio.createUnit(to_unit_string).get).get.value
|
91
|
+
end
|
92
|
+
|
93
|
+
# create an array of exterior surfaces and find range of starting construction R-value (not just insulation layer)
|
94
|
+
surfaces = model.getSurfaces
|
95
|
+
exterior_surfaces = []
|
96
|
+
exterior_surface_constructions = []
|
97
|
+
exterior_surface_construction_names = []
|
98
|
+
exterior_surface_resistance = []
|
99
|
+
surfaces.each do |surface|
|
100
|
+
if (surface.outsideBoundaryCondition == 'Outdoors') && (surface.surfaceType == 'Wall')
|
101
|
+
exterior_surfaces << surface
|
102
|
+
exterior_surface_const = surface.construction.get
|
103
|
+
# only add construction if it hasn't been added yet
|
104
|
+
if !exterior_surface_construction_names.include?(exterior_surface_const.name.to_s)
|
105
|
+
exterior_surface_constructions << exterior_surface_const.to_Construction.get
|
106
|
+
end
|
107
|
+
exterior_surface_construction_names << exterior_surface_const.name.to_s
|
108
|
+
exterior_surface_resistance << 1 / exterior_surface_const.thermalConductance.to_f
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# nothing will be done if there are no exterior surfaces
|
113
|
+
if exterior_surfaces.empty?
|
114
|
+
runner.registerAsNotApplicable('Model does not have any exterior walls.')
|
115
|
+
return true
|
116
|
+
end
|
117
|
+
|
118
|
+
# report strings for initial condition
|
119
|
+
initial_string = []
|
120
|
+
exterior_surface_constructions.uniq.each do |exterior_surface_construction|
|
121
|
+
# unit conversion of exterior surface insulation from SI units (M^2*K/W) to IP units (ft^2*h*R/Btu)
|
122
|
+
initial_conductance_ip = unit_helper(1 / exterior_surface_construction.thermalConductance.to_f, 'm^2*K/W', 'ft^2*h*R/Btu')
|
123
|
+
initial_string << "#{exterior_surface_construction.name} (R-#{(format '%.1f', initial_conductance_ip)})"
|
124
|
+
end
|
125
|
+
runner.registerInitialCondition("The building had #{initial_string.size} exterior wall constructions: #{initial_string.sort.join(', ')}.")
|
126
|
+
|
127
|
+
# hashes to track constructions and materials made by the measure, to avoid duplicates
|
128
|
+
constructions_hash_old_new = {}
|
129
|
+
constructions_hash_new_old = {} # used to get netArea of new construction and then cost objects of construction it replaced
|
130
|
+
materials_hash = {}
|
131
|
+
|
132
|
+
# array and counter for new constructions that are made, used for reporting final condition
|
133
|
+
final_constructions_array = []
|
134
|
+
|
135
|
+
# loop through all constructions and materials used on exterior walls, edit and clone
|
136
|
+
exterior_surface_constructions.each do |exterior_surface_construction|
|
137
|
+
construction_layers = exterior_surface_construction.layers
|
138
|
+
max_thermal_resistance_material = ''
|
139
|
+
max_thermal_resistance_material_index = ''
|
140
|
+
counter = 0
|
141
|
+
thermal_resistance_values = []
|
142
|
+
|
143
|
+
# loop through construction layers and infer insulation layer/material
|
144
|
+
construction_layers.each do |construction_layer|
|
145
|
+
construction_layer_r_value = construction_layer.to_OpaqueMaterial.get.thermalResistance
|
146
|
+
if !thermal_resistance_values.empty?
|
147
|
+
if construction_layer_r_value > thermal_resistance_values.max
|
148
|
+
max_thermal_resistance_material = construction_layer
|
149
|
+
max_thermal_resistance_material_index = counter
|
150
|
+
end
|
151
|
+
end
|
152
|
+
thermal_resistance_values << construction_layer_r_value
|
153
|
+
counter += 1
|
154
|
+
end
|
155
|
+
|
156
|
+
if thermal_resistance_values.max <= unit_helper(min_expected_r_value_ip, 'ft^2*h*R/Btu', 'm^2*K/W')
|
157
|
+
runner.registerWarning("Construction '#{exterior_surface_construction.name}' does not appear to have an insulation layer and was not altered.")
|
158
|
+
else
|
159
|
+
# clone the construction
|
160
|
+
final_construction = exterior_surface_construction.clone(model)
|
161
|
+
final_construction = final_construction.to_Construction.get
|
162
|
+
final_construction.setName("#{exterior_surface_construction.name} adj exterior wall insulation")
|
163
|
+
final_constructions_array << final_construction
|
164
|
+
|
165
|
+
# add construction object if it didnt exist to start with
|
166
|
+
|
167
|
+
# push to hashes
|
168
|
+
constructions_hash_old_new[exterior_surface_construction.name.to_s] = final_construction
|
169
|
+
constructions_hash_new_old[final_construction] = exterior_surface_construction # push the object to hash key vs. name
|
170
|
+
|
171
|
+
# find already cloned insulation material and link to construction
|
172
|
+
target_material = max_thermal_resistance_material
|
173
|
+
found_material = false
|
174
|
+
materials_hash.each do |orig, new|
|
175
|
+
if target_material.name.to_s == orig
|
176
|
+
new_material = new
|
177
|
+
materials_hash[max_thermal_resistance_material.name.to_s] = new_material
|
178
|
+
final_construction.eraseLayer(max_thermal_resistance_material_index)
|
179
|
+
final_construction.insertLayer(max_thermal_resistance_material_index, new_material)
|
180
|
+
found_material = true
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# clone and edit insulation material and link to construction
|
185
|
+
if found_material == false
|
186
|
+
new_material = max_thermal_resistance_material.clone(model)
|
187
|
+
new_material = new_material.to_OpaqueMaterial.get
|
188
|
+
new_material.setName("#{max_thermal_resistance_material.name}_R-value #{r_value}% increase")
|
189
|
+
materials_hash[max_thermal_resistance_material.name.to_s] = new_material
|
190
|
+
final_construction.eraseLayer(max_thermal_resistance_material_index)
|
191
|
+
final_construction.insertLayer(max_thermal_resistance_material_index, new_material)
|
192
|
+
runner.registerInfo("For construction'#{final_construction.name}', material'#{new_material.name}' was altered.")
|
193
|
+
|
194
|
+
# edit insulation material
|
195
|
+
new_material_matt = new_material.to_Material
|
196
|
+
if !new_material_matt.empty?
|
197
|
+
starting_thickness = new_material_matt.get.thickness
|
198
|
+
target_thickness = starting_thickness * (1 + r_value / 100)
|
199
|
+
final_thickness = new_material_matt.get.setThickness(target_thickness)
|
200
|
+
end
|
201
|
+
new_material_massless = new_material.to_MasslessOpaqueMaterial
|
202
|
+
if !new_material_massless.empty?
|
203
|
+
starting_thermal_resistance = new_material_massless.get.thermalResistance
|
204
|
+
final_thermal_resistance = new_material_massless.get.setThermalResistance(starting_thermal_resistance * (1 + r_value / 100))
|
205
|
+
end
|
206
|
+
new_material_airgap = new_material.to_AirGap
|
207
|
+
if !new_material_airgap.empty?
|
208
|
+
starting_thermal_resistance = new_material_airgap.get.thermalResistance
|
209
|
+
final_thermal_resistance = new_material_airgap.get.setThermalResistance(starting_thermal_resistance * (1 + r_value / 100))
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# loop through construction sets used in the model
|
216
|
+
default_construction_sets = model.getDefaultConstructionSets
|
217
|
+
default_construction_sets.each do |default_construction_set|
|
218
|
+
if default_construction_set.directUseCount > 0
|
219
|
+
default_surface_const_set = default_construction_set.defaultExteriorSurfaceConstructions
|
220
|
+
if !default_surface_const_set.empty?
|
221
|
+
starting_construction = default_surface_const_set.get.wallConstruction
|
222
|
+
|
223
|
+
# creating new default construction set
|
224
|
+
new_default_construction_set = default_construction_set.clone(model)
|
225
|
+
new_default_construction_set = new_default_construction_set.to_DefaultConstructionSet.get
|
226
|
+
new_default_construction_set.setName("#{default_construction_set.name} adj exterior wall insulation")
|
227
|
+
|
228
|
+
# create new surface set and link to construction set
|
229
|
+
new_default_surface_const_set = default_surface_const_set.get.clone(model)
|
230
|
+
new_default_surface_const_set = new_default_surface_const_set.to_DefaultSurfaceConstructions.get
|
231
|
+
new_default_surface_const_set.setName("#{default_surface_const_set.get.name} adj exterior wall insulation")
|
232
|
+
new_default_construction_set.setDefaultExteriorSurfaceConstructions(new_default_surface_const_set)
|
233
|
+
|
234
|
+
# use the hash to find the proper construction and link to new_default_surface_const_set
|
235
|
+
target_const = new_default_surface_const_set.wallConstruction
|
236
|
+
if !target_const.empty?
|
237
|
+
target_const = target_const.get.name.to_s
|
238
|
+
found_const_flag = false
|
239
|
+
constructions_hash_old_new.each do |orig, new|
|
240
|
+
if target_const == orig
|
241
|
+
final_construction = new
|
242
|
+
new_default_surface_const_set.setWallConstruction(final_construction)
|
243
|
+
found_const_flag = true
|
244
|
+
end
|
245
|
+
end
|
246
|
+
if found_const_flag == false # this should never happen but is just an extra test in case something goes wrong with the measure code
|
247
|
+
runner.registerWarning("Measure couldn't find the construction named '#{target_const}' in the exterior surface hash.")
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
# swap all uses of the old construction set for the new
|
252
|
+
construction_set_sources = default_construction_set.sources
|
253
|
+
construction_set_sources.each do |construction_set_source|
|
254
|
+
building_source = construction_set_source.to_Building
|
255
|
+
# if statement for each type of object than can use a DefaultConstructionSet
|
256
|
+
if !building_source.empty?
|
257
|
+
building_source = building_source.get
|
258
|
+
building_source.setDefaultConstructionSet(new_default_construction_set)
|
259
|
+
end
|
260
|
+
building_story_source = construction_set_source.to_BuildingStory
|
261
|
+
if !building_story_source.empty?
|
262
|
+
building_story_source = building_story_source.get
|
263
|
+
building_story_source.setDefaultConstructionSet(new_default_construction_set)
|
264
|
+
end
|
265
|
+
space_type_source = construction_set_source.to_SpaceType
|
266
|
+
if !space_type_source.empty?
|
267
|
+
space_type_source = space_type_source.get
|
268
|
+
space_type_source.setDefaultConstructionSet(new_default_construction_set)
|
269
|
+
end
|
270
|
+
space_source = construction_set_source.to_Space
|
271
|
+
if !space_source.empty?
|
272
|
+
space_source = space_source.get
|
273
|
+
space_source.setDefaultConstructionSet(new_default_construction_set)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
# link cloned and edited constructions for surfaces with hard assigned constructions
|
282
|
+
exterior_surfaces.each do |exterior_surface|
|
283
|
+
if !exterior_surface.isConstructionDefaulted && !exterior_surface.construction.empty?
|
284
|
+
|
285
|
+
# use the hash to find the proper construction and link to surface
|
286
|
+
target_const = exterior_surface.construction
|
287
|
+
if !target_const.empty?
|
288
|
+
target_const = target_const.get.name.to_s
|
289
|
+
constructions_hash_old_new.each do |orig, new|
|
290
|
+
if target_const == orig
|
291
|
+
final_construction = new
|
292
|
+
exterior_surface.setConstruction(final_construction)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# report strings for final condition
|
301
|
+
final_string = [] # not all exterior surface constructions, but only new ones made. If exterior surface didn't have insulation and was not altered we don't want to show it
|
302
|
+
affected_area_si = 0
|
303
|
+
final_constructions_array.each do |final_construction|
|
304
|
+
# unit conversion of exterior surface insulation from SI units (M^2*K/W) to IP units (ft^2*h*R/Btu)
|
305
|
+
final_conductance_ip = unit_helper(1 / final_construction.thermalConductance.to_f, 'm^2*K/W', 'ft^2*h*R/Btu')
|
306
|
+
final_string << "#{final_construction.name} (R-#{(format '%.1f', final_conductance_ip)})"
|
307
|
+
affected_area_si += final_construction.getNetArea
|
308
|
+
end
|
309
|
+
|
310
|
+
# add not applicable test if there were exterior surface constructions but none of them were altered (already enough insulation or doesn't look like insulated wall)
|
311
|
+
if affected_area_si == 0
|
312
|
+
runner.registerAsNotApplicable('No exterior walls were altered.')
|
313
|
+
return true
|
314
|
+
# affected_area_ip = affected_area_si
|
315
|
+
else
|
316
|
+
# ip construction area for reporting
|
317
|
+
affected_area_ip = unit_helper(affected_area_si, 'm^2', 'ft^2')
|
318
|
+
end
|
319
|
+
|
320
|
+
# report final condition
|
321
|
+
runner.registerFinalCondition("The existing insulation for exterior walls was increased by #{r_value}%. This was applied to #{neat_numbers(affected_area_ip, 0)} (ft^2) across #{final_string.size} exterior wall constructions: #{final_string.sort.join(', ')}.")
|
322
|
+
|
323
|
+
return true
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
# this allows the measure to be used by the application
|
328
|
+
IncreaseInsulationRValueForExteriorWallsByPercentage.new.registerWithApplication
|
@@ -0,0 +1,98 @@
|
|
1
|
+
<measure>
|
2
|
+
<schema_version>3.0</schema_version>
|
3
|
+
<name>increase_insulation_r_value_for_exterior_walls_by_percentage</name>
|
4
|
+
<uid>7508c563-22bd-49f4-b646-aac69b02a82d</uid>
|
5
|
+
<version_id>9ef20b5d-2bdd-417b-a5d9-b7f77d509133</version_id>
|
6
|
+
<version_modified>20200229T024318Z</version_modified>
|
7
|
+
<xml_checksum>EB1A0C08</xml_checksum>
|
8
|
+
<class_name>IncreaseInsulationRValueForExteriorWallsByPercentage</class_name>
|
9
|
+
<display_name>Increase R-value of Insulation for Exterior Walls By a Specified Percentage</display_name>
|
10
|
+
<description>Increase the R value of the insulation layer in wall constructinons by a percentage.</description>
|
11
|
+
<modeler_description>Insulation later is inferred by finding the existing layer with the highest thermal resistance.</modeler_description>
|
12
|
+
<arguments>
|
13
|
+
<argument>
|
14
|
+
<name>r_value</name>
|
15
|
+
<display_name>Percentage Increase of R-value for Exterior Wall Insulation.</display_name>
|
16
|
+
<type>Double</type>
|
17
|
+
<required>true</required>
|
18
|
+
<model_dependent>false</model_dependent>
|
19
|
+
<default_value>30</default_value>
|
20
|
+
</argument>
|
21
|
+
</arguments>
|
22
|
+
<outputs/>
|
23
|
+
<provenances/>
|
24
|
+
<tags>
|
25
|
+
<tag>Envelope.Opaque</tag>
|
26
|
+
</tags>
|
27
|
+
<attributes>
|
28
|
+
<attribute>
|
29
|
+
<name>Measure Function</name>
|
30
|
+
<value>Measure</value>
|
31
|
+
<datatype>string</datatype>
|
32
|
+
</attribute>
|
33
|
+
<attribute>
|
34
|
+
<name>Requires EnergyPlus Results</name>
|
35
|
+
<value>false</value>
|
36
|
+
<datatype>boolean</datatype>
|
37
|
+
</attribute>
|
38
|
+
<attribute>
|
39
|
+
<name>Measure Type</name>
|
40
|
+
<value>ModelMeasure</value>
|
41
|
+
<datatype>string</datatype>
|
42
|
+
</attribute>
|
43
|
+
<attribute>
|
44
|
+
<name>Uses SketchUp API</name>
|
45
|
+
<value>false</value>
|
46
|
+
<datatype>boolean</datatype>
|
47
|
+
</attribute>
|
48
|
+
</attributes>
|
49
|
+
<files>
|
50
|
+
<file>
|
51
|
+
<filename>EnvelopeAndLoadTestModel_01.osm</filename>
|
52
|
+
<filetype>osm</filetype>
|
53
|
+
<usage_type>test</usage_type>
|
54
|
+
<checksum>10AA8866</checksum>
|
55
|
+
</file>
|
56
|
+
<file>
|
57
|
+
<filename>ReverseTranslatedModel.osm</filename>
|
58
|
+
<filetype>osm</filetype>
|
59
|
+
<usage_type>test</usage_type>
|
60
|
+
<checksum>0B94403D</checksum>
|
61
|
+
</file>
|
62
|
+
<file>
|
63
|
+
<filename>README.md.erb</filename>
|
64
|
+
<filetype>erb</filetype>
|
65
|
+
<usage_type>readmeerb</usage_type>
|
66
|
+
<checksum>703C9964</checksum>
|
67
|
+
</file>
|
68
|
+
<file>
|
69
|
+
<filename>README.md</filename>
|
70
|
+
<filetype>md</filetype>
|
71
|
+
<usage_type>readme</usage_type>
|
72
|
+
<checksum>D4B90CE5</checksum>
|
73
|
+
</file>
|
74
|
+
<file>
|
75
|
+
<filename>LICENSE.md</filename>
|
76
|
+
<filetype>md</filetype>
|
77
|
+
<usage_type>license</usage_type>
|
78
|
+
<checksum>E0468DD6</checksum>
|
79
|
+
</file>
|
80
|
+
<file>
|
81
|
+
<version>
|
82
|
+
<software_program>OpenStudio</software_program>
|
83
|
+
<identifier>2.0.0</identifier>
|
84
|
+
<min_compatible>2.0.0</min_compatible>
|
85
|
+
</version>
|
86
|
+
<filename>measure.rb</filename>
|
87
|
+
<filetype>rb</filetype>
|
88
|
+
<usage_type>script</usage_type>
|
89
|
+
<checksum>478DC9B7</checksum>
|
90
|
+
</file>
|
91
|
+
<file>
|
92
|
+
<filename>IncreaseInsulationRValueForExteriorWalls_Test.rb</filename>
|
93
|
+
<filetype>rb</filetype>
|
94
|
+
<usage_type>test</usage_type>
|
95
|
+
<checksum>01E73CC1</checksum>
|
96
|
+
</file>
|
97
|
+
</files>
|
98
|
+
</measure>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted
|
4
|
+
provided that the following conditions are met:
|
5
|
+
|
6
|
+
(1) Redistributions of source code must retain the above copyright notice, this list of conditions
|
7
|
+
and the following disclaimer.
|
8
|
+
|
9
|
+
(2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
10
|
+
and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
11
|
+
|
12
|
+
(3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse
|
13
|
+
or promote products derived from this software without specific prior written permission from the
|
14
|
+
respective party.
|
15
|
+
|
16
|
+
(4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other
|
17
|
+
derivative works may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar
|
18
|
+
designation without specific prior written permission from Alliance for Sustainable Energy, LLC.
|
19
|
+
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
21
|
+
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
22
|
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES GOVERNMENT,
|
23
|
+
OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
25
|
+
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
26
|
+
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
27
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
###### (Automatically generated documentation)
|
4
|
+
|
5
|
+
# Increase R-value of Insulation for Roofs by a Specified Percentage.
|
6
|
+
|
7
|
+
## Description
|
8
|
+
|
9
|
+
|
10
|
+
## Modeler Description
|
11
|
+
|
12
|
+
|
13
|
+
## Measure Type
|
14
|
+
ModelMeasure
|
15
|
+
|
16
|
+
## Taxonomy
|
17
|
+
|
18
|
+
|
19
|
+
## Arguments
|
20
|
+
|
21
|
+
|
22
|
+
### Percentage Increase of R-value for Roof Insulation.
|
23
|
+
|
24
|
+
**Name:** r_value,
|
25
|
+
**Type:** Double,
|
26
|
+
**Units:** ,
|
27
|
+
**Required:** true,
|
28
|
+
**Model Dependent:** false
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<%#= README.md.erb is used to auto-generate README.md. %>
|
2
|
+
<%#= To manually maintain README.md throw away README.md.erb and manually edit README.md %>
|
3
|
+
###### (Automatically generated documentation)
|
4
|
+
|
5
|
+
# <%= name %>
|
6
|
+
|
7
|
+
## Description
|
8
|
+
<%= description %>
|
9
|
+
|
10
|
+
## Modeler Description
|
11
|
+
<%= modelerDescription %>
|
12
|
+
|
13
|
+
## Measure Type
|
14
|
+
<%= measureType %>
|
15
|
+
|
16
|
+
## Taxonomy
|
17
|
+
<%= taxonomy %>
|
18
|
+
|
19
|
+
## Arguments
|
20
|
+
|
21
|
+
<% arguments.each do |argument| %>
|
22
|
+
### <%= argument[:display_name] %>
|
23
|
+
<%= argument[:description] %>
|
24
|
+
**Name:** <%= argument[:name] %>,
|
25
|
+
**Type:** <%= argument[:type] %>,
|
26
|
+
**Units:** <%= argument[:units] %>,
|
27
|
+
**Required:** <%= argument[:required] %>,
|
28
|
+
**Model Dependent:** <%= argument[:model_dependent] %>
|
29
|
+
<% end %>
|
30
|
+
|
31
|
+
<% if arguments.size == 0 %>
|
32
|
+
<%= "This measure does not have any user arguments" %>
|
33
|
+
<% end %>
|
34
|
+
|
35
|
+
<% if outputs.size > 0 %>
|
36
|
+
## Outputs
|
37
|
+
<% output_names = [] %>
|
38
|
+
<% outputs.each do |output| %>
|
39
|
+
<% output_names << output[:display_name] %>
|
40
|
+
<% end %>
|
41
|
+
<%= output_names.join(", ") %>
|
42
|
+
<% end %>
|
@@ -0,0 +1,328 @@
|
|
1
|
+
# *******************************************************************************
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
|
3
|
+
# All rights reserved.
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
#
|
10
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
#
|
14
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
15
|
+
# may be used to endorse or promote products derived from this software without
|
16
|
+
# specific prior written permission from the respective party.
|
17
|
+
#
|
18
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
19
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
20
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
21
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
24
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
25
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
26
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
27
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
28
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
29
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
30
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
31
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
32
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
33
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
# *******************************************************************************
|
35
|
+
|
36
|
+
# start the measure
|
37
|
+
class IncreaseInsulationRValueForRoofsByPercentage < OpenStudio::Ruleset::ModelUserScript
|
38
|
+
# define the name that a user will see
|
39
|
+
def name
|
40
|
+
return 'Increase R-value of Insulation for Roofs by a Specified Percentage.'
|
41
|
+
end
|
42
|
+
|
43
|
+
# define the arguments that the user will input
|
44
|
+
def arguments(model)
|
45
|
+
args = OpenStudio::Ruleset::OSArgumentVector.new
|
46
|
+
|
47
|
+
# make an argument insulation R-value
|
48
|
+
r_value = OpenStudio::Ruleset::OSArgument.makeDoubleArgument('r_value', true)
|
49
|
+
r_value.setDisplayName('Percentage Increase of R-value for Roof Insulation.')
|
50
|
+
r_value.setDefaultValue(30.0)
|
51
|
+
args << r_value
|
52
|
+
|
53
|
+
return args
|
54
|
+
end
|
55
|
+
|
56
|
+
# define what happens when the measure is run
|
57
|
+
def run(model, runner, user_arguments)
|
58
|
+
super(model, runner, user_arguments)
|
59
|
+
|
60
|
+
# use the built-in error checking
|
61
|
+
if !runner.validateUserArguments(arguments(model), user_arguments)
|
62
|
+
return false
|
63
|
+
end
|
64
|
+
|
65
|
+
# assign the user inputs to variables
|
66
|
+
r_value = runner.getDoubleArgumentValue('r_value', user_arguments)
|
67
|
+
|
68
|
+
# set limit for minimum insulation. This is used to limit input and for inferring insulation layer in construction.
|
69
|
+
min_expected_r_value_ip = 1 # ip units
|
70
|
+
|
71
|
+
# check the R-value for reasonableness
|
72
|
+
if r_value < -100
|
73
|
+
runner.registerError('Percentage increase less than -100% is not valid.')
|
74
|
+
return false
|
75
|
+
end
|
76
|
+
|
77
|
+
# 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
|
78
|
+
def neat_numbers(number, roundto = 2) # round to 0 or 2)
|
79
|
+
if roundto == 2
|
80
|
+
number = format '%.2f', number
|
81
|
+
else
|
82
|
+
number = number.round
|
83
|
+
end
|
84
|
+
# regex to add commas
|
85
|
+
number.to_s.reverse.gsub(/([0-9]{3}(?=([0-9])))/, '\\1,').reverse
|
86
|
+
end
|
87
|
+
|
88
|
+
# helper to make it easier to do unit conversions on the fly
|
89
|
+
def unit_helper(number, from_unit_string, to_unit_string)
|
90
|
+
converted_number = OpenStudio.convert(OpenStudio::Quantity.new(number, OpenStudio.createUnit(from_unit_string).get), OpenStudio.createUnit(to_unit_string).get).get.value
|
91
|
+
end
|
92
|
+
|
93
|
+
# create an array of roofs and find range of starting construction R-value (not just insulation layer)
|
94
|
+
surfaces = model.getSurfaces
|
95
|
+
exterior_surfaces = []
|
96
|
+
exterior_surface_constructions = []
|
97
|
+
exterior_surface_construction_names = []
|
98
|
+
roof_resistance = []
|
99
|
+
surfaces.each do |surface|
|
100
|
+
if (surface.outsideBoundaryCondition == 'Outdoors') && (surface.surfaceType == 'RoofCeiling')
|
101
|
+
exterior_surfaces << surface
|
102
|
+
roof_const = surface.construction.get
|
103
|
+
# only add construction if it hasn't been added yet
|
104
|
+
if !exterior_surface_construction_names.include?(roof_const.name.to_s)
|
105
|
+
exterior_surface_constructions << roof_const.to_Construction.get
|
106
|
+
end
|
107
|
+
exterior_surface_construction_names << roof_const.name.to_s
|
108
|
+
roof_resistance << 1 / roof_const.thermalConductance.to_f
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# nothing will be done if there are no exterior surfaces
|
113
|
+
if exterior_surfaces.empty?
|
114
|
+
runner.registerAsNotApplicable('Model does not have any roofs.')
|
115
|
+
return true
|
116
|
+
end
|
117
|
+
|
118
|
+
# report strings for initial condition
|
119
|
+
initial_string = []
|
120
|
+
exterior_surface_constructions.uniq.each do |exterior_surface_construction|
|
121
|
+
# unit conversion of roof insulation from SI units (M^2*K/W) to IP units (ft^2*h*R/Btu)
|
122
|
+
initial_conductance_ip = unit_helper(1 / exterior_surface_construction.thermalConductance.to_f, 'm^2*K/W', 'ft^2*h*R/Btu')
|
123
|
+
initial_string << "#{exterior_surface_construction.name} (R-#{(format '%.1f', initial_conductance_ip)})"
|
124
|
+
end
|
125
|
+
runner.registerInitialCondition("The building had #{initial_string.size} roof constructions: #{initial_string.sort.join(', ')}.")
|
126
|
+
|
127
|
+
# hashes to track constructions and materials made by the measure, to avoid duplicates
|
128
|
+
constructions_hash_old_new = {}
|
129
|
+
constructions_hash_new_old = {} # used to get netArea of new construction and then cost objects of construction it replaced
|
130
|
+
materials_hash = {}
|
131
|
+
|
132
|
+
# array and counter for new constructions that are made, used for reporting final condition
|
133
|
+
final_constructions_array = []
|
134
|
+
|
135
|
+
# loop through all constructions and materials used on roofs, edit and clone
|
136
|
+
exterior_surface_constructions.each do |exterior_surface_construction|
|
137
|
+
construction_layers = exterior_surface_construction.layers
|
138
|
+
max_thermal_resistance_material = ''
|
139
|
+
max_thermal_resistance_material_index = ''
|
140
|
+
counter = 0
|
141
|
+
thermal_resistance_values = []
|
142
|
+
|
143
|
+
# loop through construction layers and infer insulation layer/material
|
144
|
+
construction_layers.each do |construction_layer|
|
145
|
+
construction_layer_r_value = construction_layer.to_OpaqueMaterial.get.thermalResistance
|
146
|
+
if !thermal_resistance_values.empty?
|
147
|
+
if construction_layer_r_value > thermal_resistance_values.max
|
148
|
+
max_thermal_resistance_material = construction_layer
|
149
|
+
max_thermal_resistance_material_index = counter
|
150
|
+
end
|
151
|
+
end
|
152
|
+
thermal_resistance_values << construction_layer_r_value
|
153
|
+
counter += 1
|
154
|
+
end
|
155
|
+
|
156
|
+
if thermal_resistance_values.max <= unit_helper(min_expected_r_value_ip, 'ft^2*h*R/Btu', 'm^2*K/W')
|
157
|
+
runner.registerWarning("Construction '#{exterior_surface_construction.name}' does not appear to have an insulation layer and was not altered.")
|
158
|
+
else
|
159
|
+
# clone the construction
|
160
|
+
final_construction = exterior_surface_construction.clone(model)
|
161
|
+
final_construction = final_construction.to_Construction.get
|
162
|
+
final_construction.setName("#{exterior_surface_construction.name} adj roof insulation")
|
163
|
+
final_constructions_array << final_construction
|
164
|
+
|
165
|
+
# add construction object if it didnt exist to start with
|
166
|
+
|
167
|
+
# push to hashes
|
168
|
+
constructions_hash_old_new[exterior_surface_construction.name.to_s] = final_construction
|
169
|
+
constructions_hash_new_old[final_construction] = exterior_surface_construction # push the object to hash key vs. name
|
170
|
+
|
171
|
+
# find already cloned insulation material and link to construction
|
172
|
+
target_material = max_thermal_resistance_material
|
173
|
+
found_material = false
|
174
|
+
materials_hash.each do |orig, new|
|
175
|
+
if target_material.name.to_s == orig
|
176
|
+
new_material = new
|
177
|
+
materials_hash[max_thermal_resistance_material.name.to_s] = new_material
|
178
|
+
final_construction.eraseLayer(max_thermal_resistance_material_index)
|
179
|
+
final_construction.insertLayer(max_thermal_resistance_material_index, new_material)
|
180
|
+
found_material = true
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# clone and edit insulation material and link to construction
|
185
|
+
if found_material == false
|
186
|
+
new_material = max_thermal_resistance_material.clone(model)
|
187
|
+
new_material = new_material.to_OpaqueMaterial.get
|
188
|
+
new_material.setName("#{max_thermal_resistance_material.name}_R-value #{r_value}% increase")
|
189
|
+
materials_hash[max_thermal_resistance_material.name.to_s] = new_material
|
190
|
+
final_construction.eraseLayer(max_thermal_resistance_material_index)
|
191
|
+
final_construction.insertLayer(max_thermal_resistance_material_index, new_material)
|
192
|
+
runner.registerInfo("For construction'#{final_construction.name}', material'#{new_material.name}' was altered.")
|
193
|
+
|
194
|
+
# edit insulation material
|
195
|
+
new_material_matt = new_material.to_Material
|
196
|
+
if !new_material_matt.empty?
|
197
|
+
starting_thickness = new_material_matt.get.thickness
|
198
|
+
target_thickness = starting_thickness * (1 + r_value / 100)
|
199
|
+
final_thickness = new_material_matt.get.setThickness(target_thickness)
|
200
|
+
end
|
201
|
+
new_material_massless = new_material.to_MasslessOpaqueMaterial
|
202
|
+
if !new_material_massless.empty?
|
203
|
+
starting_thermal_resistance = new_material_massless.get.thermalResistance
|
204
|
+
final_thermal_resistance = new_material_massless.get.setThermalResistance(starting_thermal_resistance * (1 + r_value / 100))
|
205
|
+
end
|
206
|
+
new_material_airgap = new_material.to_AirGap
|
207
|
+
if !new_material_airgap.empty?
|
208
|
+
starting_thermal_resistance = new_material_airgap.get.thermalResistance
|
209
|
+
final_thermal_resistance = new_material_airgap.get.setThermalResistance(starting_thermal_resistance * (1 + r_value / 100))
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# loop through construction sets used in the model
|
216
|
+
default_construction_sets = model.getDefaultConstructionSets
|
217
|
+
default_construction_sets.each do |default_construction_set|
|
218
|
+
if default_construction_set.directUseCount > 0
|
219
|
+
default_surface_const_set = default_construction_set.defaultExteriorSurfaceConstructions
|
220
|
+
if !default_surface_const_set.empty?
|
221
|
+
starting_construction = default_surface_const_set.get.roofCeilingConstruction
|
222
|
+
|
223
|
+
# creating new default construction set
|
224
|
+
new_default_construction_set = default_construction_set.clone(model)
|
225
|
+
new_default_construction_set = new_default_construction_set.to_DefaultConstructionSet.get
|
226
|
+
new_default_construction_set.setName("#{default_construction_set.name} adj roof insulation")
|
227
|
+
|
228
|
+
# create new surface set and link to construction set
|
229
|
+
new_default_surface_const_set = default_surface_const_set.get.clone(model)
|
230
|
+
new_default_surface_const_set = new_default_surface_const_set.to_DefaultSurfaceConstructions.get
|
231
|
+
new_default_surface_const_set.setName("#{default_surface_const_set.get.name} adj roof insulation")
|
232
|
+
new_default_construction_set.setDefaultExteriorSurfaceConstructions(new_default_surface_const_set)
|
233
|
+
|
234
|
+
# use the hash to find the proper construction and link to new_default_surface_const_set
|
235
|
+
target_const = new_default_surface_const_set.roofCeilingConstruction
|
236
|
+
if !target_const.empty?
|
237
|
+
target_const = target_const.get.name.to_s
|
238
|
+
found_const_flag = false
|
239
|
+
constructions_hash_old_new.each do |orig, new|
|
240
|
+
if target_const == orig
|
241
|
+
final_construction = new
|
242
|
+
new_default_surface_const_set.setRoofCeilingConstruction(final_construction)
|
243
|
+
found_const_flag = true
|
244
|
+
end
|
245
|
+
end
|
246
|
+
if found_const_flag == false # this should never happen but is just an extra test in case something goes wrong with the measure code
|
247
|
+
runner.registerWarning("Measure couldn't find the construction named '#{target_const}' in the exterior surface hash.")
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
# swap all uses of the old construction set for the new
|
252
|
+
construction_set_sources = default_construction_set.sources
|
253
|
+
construction_set_sources.each do |construction_set_source|
|
254
|
+
building_source = construction_set_source.to_Building
|
255
|
+
# if statement for each type of object than can use a DefaultConstructionSet
|
256
|
+
if !building_source.empty?
|
257
|
+
building_source = building_source.get
|
258
|
+
building_source.setDefaultConstructionSet(new_default_construction_set)
|
259
|
+
end
|
260
|
+
building_story_source = construction_set_source.to_BuildingStory
|
261
|
+
if !building_story_source.empty?
|
262
|
+
building_story_source = building_story_source.get
|
263
|
+
building_story_source.setDefaultConstructionSet(new_default_construction_set)
|
264
|
+
end
|
265
|
+
space_type_source = construction_set_source.to_SpaceType
|
266
|
+
if !space_type_source.empty?
|
267
|
+
space_type_source = space_type_source.get
|
268
|
+
space_type_source.setDefaultConstructionSet(new_default_construction_set)
|
269
|
+
end
|
270
|
+
space_source = construction_set_source.to_Space
|
271
|
+
if !space_source.empty?
|
272
|
+
space_source = space_source.get
|
273
|
+
space_source.setDefaultConstructionSet(new_default_construction_set)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
# link cloned and edited constructions for surfaces with hard assigned constructions
|
282
|
+
exterior_surfaces.each do |exterior_surface|
|
283
|
+
if !exterior_surface.isConstructionDefaulted && !exterior_surface.construction.empty?
|
284
|
+
|
285
|
+
# use the hash to find the proper construction and link to surface
|
286
|
+
target_const = exterior_surface.construction
|
287
|
+
if !target_const.empty?
|
288
|
+
target_const = target_const.get.name.to_s
|
289
|
+
constructions_hash_old_new.each do |orig, new|
|
290
|
+
if target_const == orig
|
291
|
+
final_construction = new
|
292
|
+
exterior_surface.setConstruction(final_construction)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# report strings for final condition
|
301
|
+
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
|
302
|
+
affected_area_si = 0
|
303
|
+
final_constructions_array.each do |final_construction|
|
304
|
+
# unit conversion of roof insulation from SI units (M^2*K/W) to IP units (ft^2*h*R/Btu)
|
305
|
+
final_conductance_ip = unit_helper(1 / final_construction.thermalConductance.to_f, 'm^2*K/W', 'ft^2*h*R/Btu')
|
306
|
+
final_string << "#{final_construction.name} (R-#{(format '%.1f', final_conductance_ip)})"
|
307
|
+
affected_area_si += final_construction.getNetArea
|
308
|
+
end
|
309
|
+
|
310
|
+
# 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)
|
311
|
+
if affected_area_si == 0
|
312
|
+
runner.registerAsNotApplicable('No roofs were altered.')
|
313
|
+
return true
|
314
|
+
# affected_area_ip = affected_area_si
|
315
|
+
else
|
316
|
+
# ip construction area for reporting
|
317
|
+
affected_area_ip = unit_helper(affected_area_si, 'm^2', 'ft^2')
|
318
|
+
end
|
319
|
+
|
320
|
+
# report final condition
|
321
|
+
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(', ')}.")
|
322
|
+
|
323
|
+
return true
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
# this allows the measure to be used by the application
|
328
|
+
IncreaseInsulationRValueForRoofsByPercentage.new.registerWithApplication
|
@@ -0,0 +1,98 @@
|
|
1
|
+
<measure>
|
2
|
+
<schema_version>3.0</schema_version>
|
3
|
+
<name>increase_insulation_r_value_for_roofs_by_percentage</name>
|
4
|
+
<uid>807d3ebf-c89b-4b93-b400-110ca060b2bb</uid>
|
5
|
+
<version_id>9845f31c-01a7-4db1-9a3c-8e773f01a860</version_id>
|
6
|
+
<version_modified>20200229T024315Z</version_modified>
|
7
|
+
<xml_checksum>EB1A0C08</xml_checksum>
|
8
|
+
<class_name>IncreaseInsulationRValueForRoofsByPercentage</class_name>
|
9
|
+
<display_name>Increase R-value of Insulation for Roofs by a Specified Percentage.</display_name>
|
10
|
+
<description>Increase the R value of the insulation layer in roof constructinons by a percentage.</description>
|
11
|
+
<modeler_description>Insulation later is inferred by finding the existing layer with the highest thermal resistance.</modeler_description>
|
12
|
+
<arguments>
|
13
|
+
<argument>
|
14
|
+
<name>r_value</name>
|
15
|
+
<display_name>Percentage Increase of R-value for Roof Insulation.</display_name>
|
16
|
+
<type>Double</type>
|
17
|
+
<required>true</required>
|
18
|
+
<model_dependent>false</model_dependent>
|
19
|
+
<default_value>30</default_value>
|
20
|
+
</argument>
|
21
|
+
</arguments>
|
22
|
+
<outputs/>
|
23
|
+
<provenances/>
|
24
|
+
<tags>
|
25
|
+
<tag>Envelope.Opaque</tag>
|
26
|
+
</tags>
|
27
|
+
<attributes>
|
28
|
+
<attribute>
|
29
|
+
<name>Measure Function</name>
|
30
|
+
<value>Measure</value>
|
31
|
+
<datatype>string</datatype>
|
32
|
+
</attribute>
|
33
|
+
<attribute>
|
34
|
+
<name>Requires EnergyPlus Results</name>
|
35
|
+
<value>false</value>
|
36
|
+
<datatype>boolean</datatype>
|
37
|
+
</attribute>
|
38
|
+
<attribute>
|
39
|
+
<name>Measure Type</name>
|
40
|
+
<value>ModelMeasure</value>
|
41
|
+
<datatype>string</datatype>
|
42
|
+
</attribute>
|
43
|
+
<attribute>
|
44
|
+
<name>Uses SketchUp API</name>
|
45
|
+
<value>false</value>
|
46
|
+
<datatype>boolean</datatype>
|
47
|
+
</attribute>
|
48
|
+
</attributes>
|
49
|
+
<files>
|
50
|
+
<file>
|
51
|
+
<filename>EnvelopeAndLoadTestModel_01.osm</filename>
|
52
|
+
<filetype>osm</filetype>
|
53
|
+
<usage_type>test</usage_type>
|
54
|
+
<checksum>10AA8866</checksum>
|
55
|
+
</file>
|
56
|
+
<file>
|
57
|
+
<filename>ReverseTranslatedModel.osm</filename>
|
58
|
+
<filetype>osm</filetype>
|
59
|
+
<usage_type>test</usage_type>
|
60
|
+
<checksum>0B94403D</checksum>
|
61
|
+
</file>
|
62
|
+
<file>
|
63
|
+
<filename>README.md.erb</filename>
|
64
|
+
<filetype>erb</filetype>
|
65
|
+
<usage_type>readmeerb</usage_type>
|
66
|
+
<checksum>703C9964</checksum>
|
67
|
+
</file>
|
68
|
+
<file>
|
69
|
+
<filename>README.md</filename>
|
70
|
+
<filetype>md</filetype>
|
71
|
+
<usage_type>readme</usage_type>
|
72
|
+
<checksum>AFA7235D</checksum>
|
73
|
+
</file>
|
74
|
+
<file>
|
75
|
+
<filename>LICENSE.md</filename>
|
76
|
+
<filetype>md</filetype>
|
77
|
+
<usage_type>license</usage_type>
|
78
|
+
<checksum>E0468DD6</checksum>
|
79
|
+
</file>
|
80
|
+
<file>
|
81
|
+
<version>
|
82
|
+
<software_program>OpenStudio</software_program>
|
83
|
+
<identifier>2.0.0</identifier>
|
84
|
+
<min_compatible>2.0.0</min_compatible>
|
85
|
+
</version>
|
86
|
+
<filename>measure.rb</filename>
|
87
|
+
<filetype>rb</filetype>
|
88
|
+
<usage_type>script</usage_type>
|
89
|
+
<checksum>4F106AF3</checksum>
|
90
|
+
</file>
|
91
|
+
<file>
|
92
|
+
<filename>IncreaseInsulationRValueForRoofs_Test.rb</filename>
|
93
|
+
<filetype>rb</filetype>
|
94
|
+
<usage_type>test</usage_type>
|
95
|
+
<checksum>62EC1368</checksum>
|
96
|
+
</file>
|
97
|
+
</files>
|
98
|
+
</measure>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openstudio-ee
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Goldwasser
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-12-
|
12
|
+
date: 2020-12-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -168,11 +168,21 @@ files:
|
|
168
168
|
- lib/measures/IncreaseInsulationRValueForExteriorWalls/README.md.erb
|
169
169
|
- lib/measures/IncreaseInsulationRValueForExteriorWalls/measure.rb
|
170
170
|
- lib/measures/IncreaseInsulationRValueForExteriorWalls/measure.xml
|
171
|
+
- lib/measures/IncreaseInsulationRValueForExteriorWallsByPercentage/LICENSE.md
|
172
|
+
- lib/measures/IncreaseInsulationRValueForExteriorWallsByPercentage/README.md
|
173
|
+
- lib/measures/IncreaseInsulationRValueForExteriorWallsByPercentage/README.md.erb
|
174
|
+
- lib/measures/IncreaseInsulationRValueForExteriorWallsByPercentage/measure.rb
|
175
|
+
- lib/measures/IncreaseInsulationRValueForExteriorWallsByPercentage/measure.xml
|
171
176
|
- lib/measures/IncreaseInsulationRValueForRoofs/LICENSE.md
|
172
177
|
- lib/measures/IncreaseInsulationRValueForRoofs/README.md
|
173
178
|
- lib/measures/IncreaseInsulationRValueForRoofs/README.md.erb
|
174
179
|
- lib/measures/IncreaseInsulationRValueForRoofs/measure.rb
|
175
180
|
- lib/measures/IncreaseInsulationRValueForRoofs/measure.xml
|
181
|
+
- lib/measures/IncreaseInsulationRValueForRoofsByPercentage/LICENSE.md
|
182
|
+
- lib/measures/IncreaseInsulationRValueForRoofsByPercentage/README.md
|
183
|
+
- lib/measures/IncreaseInsulationRValueForRoofsByPercentage/README.md.erb
|
184
|
+
- lib/measures/IncreaseInsulationRValueForRoofsByPercentage/measure.rb
|
185
|
+
- lib/measures/IncreaseInsulationRValueForRoofsByPercentage/measure.xml
|
176
186
|
- lib/measures/ReduceElectricEquipmentLoadsByPercentage/LICENSE.md
|
177
187
|
- lib/measures/ReduceElectricEquipmentLoadsByPercentage/README.md
|
178
188
|
- lib/measures/ReduceElectricEquipmentLoadsByPercentage/README.md.erb
|
@@ -239,7 +249,7 @@ licenses: []
|
|
239
249
|
metadata:
|
240
250
|
bug_tracker_uri: https://github.com/NREL/openstudio-ee-gem/issues
|
241
251
|
changelog_uri: https://github.com/NREL/openstudio-ee-gem/blob/develop/CHANGELOG.md
|
242
|
-
source_code_uri: https://github.com/NREL/openstudio-ee-gem/tree/v0.3.
|
252
|
+
source_code_uri: https://github.com/NREL/openstudio-ee-gem/tree/v0.3.1
|
243
253
|
post_install_message:
|
244
254
|
rdoc_options: []
|
245
255
|
require_paths:
|