openstudio-ee 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|