openstudio-standards 0.2.0.rc1 → 0.2.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/data/standards/export_OpenStudio_libraries.rb +392 -376
- data/data/standards/manage_OpenStudio_Standards.rb +0 -1
- data/lib/openstudio-standards/btap/fileio.rb +0 -1
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Hospital.rb +2 -2
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeHotel.rb +2 -2
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.PrimarySchool.rb +2 -2
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SecondarySchool.rb +2 -2
- data/lib/openstudio-standards/refs/references.rb +13 -0
- data/lib/openstudio-standards/standards/Standards.Construction.rb +6 -6
- data/lib/openstudio-standards/standards/Standards.Model.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.Pump.rb +18 -7
- data/lib/openstudio-standards/standards/Standards.ScheduleRuleset.rb +2 -2
- data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +7 -7
- data/lib/openstudio-standards/standards/icc_iecc/icc_iecc.rb +9 -0
- data/lib/openstudio-standards/standards/icc_iecc/icc_iecc_2015/icc_iecc_2015.rb +16 -0
- data/lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb +0 -1
- data/lib/openstudio-standards/standards/necb/necb_2015/necb_2015.rb +0 -1
- data/lib/openstudio-standards/standards/oeesc/oeesc.rb +9 -0
- data/lib/openstudio-standards/standards/oeesc/oeesc_2014/oeesc_2014.rb +16 -0
- data/lib/openstudio-standards/version.rb +1 -1
- data/lib/openstudio-standards.rb +6 -0
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7971c760a2256abb5458a28ad4e0d31a9364acca
|
4
|
+
data.tar.gz: b4ed3ac1b33749ad8511de8b22dac45052074476
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7156d8390581e7633b5ec60a0fb1d44f8bb1eb78876eaf5b4ab26adcddededd0fe2b5e6a3e411d1721cce3532e5cb1c7d108f54ccfe00148555fb42b97502055
|
7
|
+
data.tar.gz: 8a8c9b87d8796999ffcee7319ec59f109513f5a7ed2057ac1b5853936263781a78797febee97909888af385c51a3db17d92a2b7402843299d9e63cf78b238f5d
|
@@ -10,14 +10,15 @@ require 'openstudio'
|
|
10
10
|
require_relative '../../lib/openstudio-standards'
|
11
11
|
|
12
12
|
def export_openstudio_libraries
|
13
|
+
start_time = Time.now
|
13
14
|
|
14
15
|
### Define what to include in the libraries ###
|
15
|
-
include_construction_sets = true # Construction Sets, Constructions, and Materials
|
16
|
-
include_space_types = true # Space Types, Internal Loads, and associated Schedule Sets and Schedules
|
17
16
|
include_boilers = true # BoilerHotWater
|
18
17
|
include_chillers = true # ChillerElectricEIR
|
19
18
|
include_unitary_acs = true # CoilCoolingDXSingleSpeed
|
20
|
-
include_heat_pumps =
|
19
|
+
include_heat_pumps = false # CoilCoolingDXSingleSpeed, CoilHeatingDXSingleSpeed, AirLoopHVACUnitaryHeatPump
|
20
|
+
include_space_types = true # Space Types, Internal Loads, and associated Schedule Sets and Schedules
|
21
|
+
include_construction_sets = true # Construction Sets, Constructions, and Materials
|
21
22
|
|
22
23
|
# Make an initial Standard to access the library data
|
23
24
|
std = Standard.build('90.1-2013')
|
@@ -27,412 +28,427 @@ def export_openstudio_libraries
|
|
27
28
|
templates_to_climate_zones = JSON.parse(temp)
|
28
29
|
|
29
30
|
# Make a library model for each template
|
30
|
-
template_to_lib_models = {}
|
31
31
|
std.standards_data["templates"].each do |template|
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
|
33
|
+
# Wrap each library creation in a begin/rescue because
|
34
|
+
# the entire process can take a long time and
|
35
|
+
# we don't want to lose all templates if one fails
|
35
36
|
begin
|
36
|
-
data['standard_applier'] = Standard.build(template_name)
|
37
|
-
template_to_lib_models[template_name] = data
|
38
|
-
rescue Exception => e
|
39
|
-
puts "'#{template_name}' is not defined in OpenStudio-Standards yet"
|
40
|
-
end
|
41
|
-
end
|
42
37
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
# Add a construction set for each valid climate zone
|
53
|
-
templates_to_climate_zones[props['template']].each do |climate_zone|
|
54
|
-
construction_set = std_applier.model_add_construction_set(model,
|
55
|
-
climate_zone,
|
56
|
-
props['building_type'],
|
57
|
-
props['space_type'],
|
58
|
-
props['is_residential'])
|
38
|
+
# Make a Standard for this template
|
39
|
+
template_name = template['name']
|
40
|
+
puts "*** Making #{template_name} ***"
|
41
|
+
template_start_time = Time.now
|
42
|
+
puts "* Started #{template_name} at: #{template_start_time}"
|
43
|
+
begin
|
44
|
+
std_applier = Standard.build(template_name)
|
45
|
+
rescue Exception => e
|
46
|
+
puts "'#{template_name}' is not defined in OpenStudio-Standards yet"
|
59
47
|
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# Space Types
|
64
|
-
if include_space_types
|
65
|
-
std.standards_data['space_types'].each do |props|
|
66
|
-
lib = template_to_lib_models[props['template']]
|
67
|
-
next if lib.nil? # Skip unsupported templates
|
68
|
-
model = lib['model']
|
69
|
-
std_applier = lib['standard_applier']
|
70
48
|
|
71
|
-
#
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
49
|
+
# Reset the openstudio-standards log
|
50
|
+
reset_log
|
51
|
+
|
52
|
+
next unless template_name == '90.1-2004'
|
53
|
+
|
54
|
+
# Make an empty model
|
55
|
+
model = OpenStudio::Model::Model.new
|
56
|
+
|
57
|
+
# Boilers
|
58
|
+
if include_boilers
|
59
|
+
puts "* Boilers *"
|
60
|
+
std.standards_data['boilers'].each do |props|
|
61
|
+
next unless props['template'] == template_name
|
62
|
+
|
63
|
+
# Make a new boiler
|
64
|
+
boiler = OpenStudio::Model::BoilerHotWater.new(model)
|
65
|
+
# Fuel Type
|
66
|
+
case props['fuel_type']
|
67
|
+
when 'Gas'
|
68
|
+
boiler.setFuelType('NaturalGas')
|
69
|
+
when 'Electric'
|
70
|
+
boiler.setFuelType('Electricity')
|
71
|
+
when 'Oil'
|
72
|
+
boiler.setFuelType('FuelOil#2')
|
73
|
+
end
|
74
|
+
# Set capacity to middle of range
|
75
|
+
min_cap_btu_per_hr = props['minimum_capacity'].to_f
|
76
|
+
max_cap_btu_per_hr = props['maximum_capacity'].to_f
|
77
|
+
mid_cap_btu_per_hr = (min_cap_btu_per_hr + max_cap_btu_per_hr) / 2
|
78
|
+
mid_cap_w = OpenStudio.convert(mid_cap_btu_per_hr, 'Btu/hr', 'W').get
|
79
|
+
boiler.setNominalCapacity(mid_cap_w)
|
80
|
+
|
81
|
+
# Apply the standard
|
82
|
+
std_applier.boiler_hot_water_apply_efficiency_and_curves(boiler)
|
83
|
+
|
84
|
+
# Reset the capacity
|
85
|
+
boiler.autosizeNominalCapacity
|
86
|
+
|
87
|
+
# Modify the name of the boiler to reflect the capacity range
|
88
|
+
min_cap_kbtu_per_hr = OpenStudio.convert(min_cap_btu_per_hr, 'Btu/hr', 'kBtu/hr').get.round
|
89
|
+
max_cap_kbtu_per_hr = OpenStudio.convert(max_cap_btu_per_hr, 'Btu/hr', 'kBtu/hr').get.round
|
90
|
+
|
91
|
+
old_name = boiler.name.get.to_s
|
92
|
+
m = old_name.match(/(\d+)kBtu\/hr/)
|
93
|
+
if m
|
94
|
+
# Put the fuel type into the name
|
95
|
+
old_type = 'Boiler Hot Water 1'
|
96
|
+
new_type = "#{props['fuel_type']} Boiler"
|
97
|
+
new_name = old_name.gsub(old_type, new_type)
|
98
|
+
# Swap out the capacity number for a range
|
99
|
+
old_cap = m[1]
|
100
|
+
if max_cap_kbtu_per_hr == 10_000_000 # Value representing infinity
|
101
|
+
new_cap = "> #{min_cap_kbtu_per_hr}"
|
102
|
+
else
|
103
|
+
new_cap = "#{min_cap_kbtu_per_hr}-#{max_cap_kbtu_per_hr}"
|
104
|
+
end
|
105
|
+
new_name = new_name.gsub(old_cap, new_cap)
|
106
|
+
boiler.setName(new_name)
|
107
|
+
puts "#{props['template']}: #{boiler.name.get.to_s}"
|
108
|
+
end
|
76
109
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
# Loads
|
81
|
-
std_applier.space_type_apply_internal_loads(space_type, true, true, true, true, true, true)
|
110
|
+
end
|
111
|
+
end
|
82
112
|
|
83
|
-
#
|
84
|
-
|
113
|
+
# Chillers
|
114
|
+
if include_chillers
|
115
|
+
puts "* Chillers *"
|
116
|
+
std.standards_data['chillers'].each do |props|
|
117
|
+
next unless props['template'] == template_name
|
118
|
+
|
119
|
+
# Skip absorption chillers
|
120
|
+
next unless props['absorption_type'].nil?
|
121
|
+
|
122
|
+
# Skip interim chiller efficiency requirements
|
123
|
+
next unless props['end_date'] == "2999-09-09T00:00:00+00:00"
|
124
|
+
|
125
|
+
# Make a new chiller
|
126
|
+
chiller = OpenStudio::Model::ChillerElectricEIR.new(model)
|
127
|
+
# Set capacity to middle of range
|
128
|
+
min_cap_tons = props['minimum_capacity'].to_f
|
129
|
+
max_cap_tons = props['maximum_capacity'].to_f
|
130
|
+
mid_cap_tons = (min_cap_tons + max_cap_tons) / 2
|
131
|
+
mid_cap_w = OpenStudio.convert(mid_cap_tons, 'ton', 'W').get
|
132
|
+
chiller.setReferenceCapacity(mid_cap_w)
|
133
|
+
|
134
|
+
# Add the chiller properties to the name, because this is what
|
135
|
+
# the standards currently work off of.
|
136
|
+
if props['cooling_type'] == 'AirCooled'
|
137
|
+
new_name = "#{props['cooling_type']} Chiller #{props['condenser_type']}"
|
138
|
+
elsif props['cooling_type'] == 'WaterCooled'
|
139
|
+
new_name = "#{props['cooling_type']} #{props['compressor_type']} Chiller"
|
140
|
+
else
|
141
|
+
new_name = chiller.name.get
|
142
|
+
end
|
143
|
+
chiller.setName(new_name)
|
144
|
+
|
145
|
+
# Apply the standard
|
146
|
+
std_applier.chiller_electric_eir_apply_efficiency_and_curves(chiller, nil)
|
147
|
+
|
148
|
+
# Reset the capacity
|
149
|
+
chiller.autosizeReferenceCapacity
|
150
|
+
|
151
|
+
# Modify the name of the chiller to reflect the capacity range
|
152
|
+
old_name = chiller.name.get.to_s
|
153
|
+
m = old_name.match(/(\d+)tons/)
|
154
|
+
if m
|
155
|
+
# Put the fuel type into the name
|
156
|
+
old_type = 'Chiller Electric EIR 1'
|
157
|
+
new_type = 'Chiller'
|
158
|
+
new_name = old_name.gsub(old_type, new_type)
|
159
|
+
# Swap out the capacity number for a range
|
160
|
+
old_cap = m[1]
|
161
|
+
if max_cap_tons == 10_000 # Value representing infinity
|
162
|
+
new_cap = "> #{min_cap_tons.round}"
|
163
|
+
else
|
164
|
+
new_cap = "#{min_cap_tons.round}-#{max_cap_tons.round}"
|
165
|
+
end
|
166
|
+
new_name = new_name.gsub(old_cap, new_cap)
|
167
|
+
chiller.setName(new_name)
|
168
|
+
puts "#{props['template']}: #{chiller.name.get.to_s}"
|
169
|
+
end
|
85
170
|
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
# Boilers
|
90
|
-
if include_boilers
|
91
|
-
std.standards_data['boilers'].each do |props|
|
92
|
-
lib = template_to_lib_models[props['template']]
|
93
|
-
next if lib.nil? # Skip unsupported templates
|
94
|
-
# Skip NECB 2011 for now
|
95
|
-
next if props['template'] == 'NECB 2011'
|
96
|
-
model = lib['model']
|
97
|
-
std_applier = lib['standard_applier']
|
98
|
-
|
99
|
-
# Make a new boiler
|
100
|
-
boiler = OpenStudio::Model::BoilerHotWater.new(model)
|
101
|
-
# Fuel Type
|
102
|
-
case props['fuel_type']
|
103
|
-
when 'Gas'
|
104
|
-
boiler.setFuelType('NaturalGas')
|
105
|
-
when 'Electric'
|
106
|
-
boiler.setFuelType('Electricity')
|
107
|
-
when 'Oil'
|
108
|
-
boiler.setFuelType('FuelOil#2')
|
109
|
-
end
|
110
|
-
# Set capacity to middle of range
|
111
|
-
min_cap_btu_per_hr = props['minimum_capacity'].to_f
|
112
|
-
max_cap_btu_per_hr = props['maximum_capacity'].to_f
|
113
|
-
mid_cap_btu_per_hr = (min_cap_btu_per_hr + max_cap_btu_per_hr) / 2
|
114
|
-
mid_cap_w = OpenStudio.convert(mid_cap_btu_per_hr, 'Btu/hr', 'W').get
|
115
|
-
boiler.setNominalCapacity(mid_cap_w)
|
116
|
-
|
117
|
-
# Apply the standard
|
118
|
-
std_applier.boiler_hot_water_apply_efficiency_and_curves(boiler)
|
119
|
-
|
120
|
-
# Reset the capacity
|
121
|
-
boiler.autosizeNominalCapacity
|
122
|
-
|
123
|
-
# Modify the name of the boiler to reflect the capacity range
|
124
|
-
min_cap_kbtu_per_hr = OpenStudio.convert(min_cap_btu_per_hr, 'Btu/hr', 'kBtu/hr').get.round
|
125
|
-
max_cap_kbtu_per_hr = OpenStudio.convert(max_cap_btu_per_hr, 'Btu/hr', 'kBtu/hr').get.round
|
126
|
-
|
127
|
-
old_name = boiler.name.get.to_s
|
128
|
-
m = old_name.match(/(\d+)kBtu\/hr/)
|
129
|
-
if m
|
130
|
-
# Put the fuel type into the name
|
131
|
-
old_type = 'Boiler Hot Water 1'
|
132
|
-
new_type = "#{props['fuel_type']} Boiler"
|
133
|
-
new_name = old_name.gsub(old_type, new_type)
|
134
|
-
# Swap out the capacity number for a range
|
135
|
-
old_cap = m[1]
|
136
|
-
if max_cap_kbtu_per_hr == 10_000_000 # Value representing infinity
|
137
|
-
new_cap = "> #{min_cap_kbtu_per_hr}"
|
138
|
-
else
|
139
|
-
new_cap = "#{min_cap_kbtu_per_hr}-#{max_cap_kbtu_per_hr}"
|
140
171
|
end
|
141
|
-
new_name = new_name.gsub(old_cap, new_cap)
|
142
|
-
boiler.setName(new_name)
|
143
|
-
puts "#{props['template']}: #{boiler.name.get.to_s}"
|
144
172
|
end
|
145
173
|
|
146
|
-
|
147
|
-
|
174
|
+
# Unitary AC
|
175
|
+
if include_unitary_acs
|
176
|
+
puts "* Unitary ACs *"
|
177
|
+
std.standards_data['unitary_acs'].each do |props|
|
178
|
+
next unless props['template'] == template_name
|
179
|
+
|
180
|
+
# Skip interim efficiency requirements
|
181
|
+
next unless props['end_date'] == "2999-09-09T00:00:00+00:00"
|
182
|
+
|
183
|
+
# Make a new DX coil
|
184
|
+
dx_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model)
|
185
|
+
# Set capacity to middle of range
|
186
|
+
min_cap_btu_per_hr = props['minimum_capacity'].to_f
|
187
|
+
max_cap_btu_per_hr = props['maximum_capacity'].to_f
|
188
|
+
mid_cap_btu_per_hr = (min_cap_btu_per_hr + max_cap_btu_per_hr) / 2
|
189
|
+
mid_cap_w = OpenStudio.convert(mid_cap_btu_per_hr, 'Btu/hr', 'W').get
|
190
|
+
dx_coil.setRatedTotalCoolingCapacity(mid_cap_w)
|
191
|
+
|
192
|
+
# Add the subcategory to the name so that it
|
193
|
+
# can be used by the efficiency lookup
|
194
|
+
dx_coil.setName("#{dx_coil.name} #{props['subcategory']}")
|
195
|
+
|
196
|
+
# If it is a PTAC coil, add to PTAC
|
197
|
+
if props['subcategory'] == 'PTAC'
|
198
|
+
htg_coil = nil
|
199
|
+
if props['heating_type'] == 'Electric Resistance or None'
|
200
|
+
htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model)
|
201
|
+
htg_coil.setName('PTAC Electric Backup Htg Coil')
|
202
|
+
else
|
203
|
+
htg_coil = OpenStudio::Model::CoilHeatingGas.new(model)
|
204
|
+
htg_coil.setName('PTAC Gas Backup Htg Coil')
|
205
|
+
end
|
206
|
+
fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule)
|
207
|
+
fan.setName("PTAC Supply Fan")
|
208
|
+
ptac = OpenStudio::Model::ZoneHVACPackagedTerminalAirConditioner.new(model,
|
209
|
+
model.alwaysOnDiscreteSchedule,
|
210
|
+
fan,
|
211
|
+
htg_coil,
|
212
|
+
dx_coil)
|
213
|
+
end
|
214
|
+
|
215
|
+
# Apply the standard
|
216
|
+
std_applier.coil_cooling_dx_single_speed_apply_efficiency_and_curves(dx_coil, {})
|
217
|
+
|
218
|
+
# Reset the capacity
|
219
|
+
dx_coil.autosizeRatedTotalCoolingCapacity
|
220
|
+
|
221
|
+
# Modify the name of the boiler to reflect the capacity range
|
222
|
+
min_cap_kbtu_per_hr = OpenStudio.convert(min_cap_btu_per_hr, 'Btu/hr', 'kBtu/hr').get.round
|
223
|
+
max_cap_kbtu_per_hr = OpenStudio.convert(max_cap_btu_per_hr, 'Btu/hr', 'kBtu/hr').get.round
|
224
|
+
|
225
|
+
# Modify the name of the dx_coil to reflect the capacity range
|
226
|
+
old_name = dx_coil.name.get.to_s
|
227
|
+
m = old_name.match(/(\d+)kBtu\/hr/)
|
228
|
+
if m
|
229
|
+
# Put the fuel type into the name
|
230
|
+
old_type = "Coil Cooling DX Single Speed 1 #{props['subcategory']}"
|
231
|
+
new_type = "#{props['cooling_type']} #{props['heating_type']} #{props['subcategory']} DX"
|
232
|
+
new_name = old_name.gsub(old_type, new_type)
|
233
|
+
# Swap out the capacity number for a range
|
234
|
+
old_cap = m[1]
|
235
|
+
if max_cap_kbtu_per_hr == 10_000 # Value representing infinity
|
236
|
+
new_cap = "> #{min_cap_kbtu_per_hr}"
|
237
|
+
else
|
238
|
+
new_cap = "#{min_cap_kbtu_per_hr}-#{max_cap_kbtu_per_hr}"
|
239
|
+
end
|
240
|
+
new_name = new_name.gsub(old_cap, new_cap)
|
241
|
+
dx_coil.setName(new_name)
|
242
|
+
puts "#{props['template']}: #{dx_coil.name.get.to_s}"
|
243
|
+
|
244
|
+
# Rename PTAC too
|
245
|
+
if props['subcategory'] == 'PTAC'
|
246
|
+
ptac.setName("PTAC #{new_name}")
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
148
250
|
|
149
|
-
# Chillers
|
150
|
-
if include_chillers
|
151
|
-
std.standards_data['chillers'].each do |props|
|
152
|
-
lib = template_to_lib_models[props['template']]
|
153
|
-
next if lib.nil? # Skip unsupported templates
|
154
|
-
# Skip NECB 2011 for now
|
155
|
-
next if props['template'] == 'NECB 2011'
|
156
|
-
model = lib['model']
|
157
|
-
std_applier = lib['standard_applier']
|
158
|
-
|
159
|
-
# Skip absorption chillers
|
160
|
-
next unless props['absorption_type'].nil?
|
161
|
-
|
162
|
-
# Skip interim chiller efficiency requirements
|
163
|
-
next unless props['end_date'] == "2999-09-09T00:00:00+00:00"
|
164
|
-
|
165
|
-
# Make a new chiller
|
166
|
-
chiller = OpenStudio::Model::ChillerElectricEIR.new(model)
|
167
|
-
# Set capacity to middle of range
|
168
|
-
min_cap_tons = props['minimum_capacity'].to_f
|
169
|
-
max_cap_tons = props['maximum_capacity'].to_f
|
170
|
-
mid_cap_tons = (min_cap_tons + max_cap_tons) / 2
|
171
|
-
mid_cap_w = OpenStudio.convert(mid_cap_tons, 'ton', 'W').get
|
172
|
-
chiller.setReferenceCapacity(mid_cap_w)
|
173
|
-
|
174
|
-
# Add the chiller properties to the name, because this is what
|
175
|
-
# the standards currently work off of.
|
176
|
-
if props['cooling_type'] == 'AirCooled'
|
177
|
-
new_name = "#{props['cooling_type']} Chiller #{props['condenser_type']}"
|
178
|
-
elsif props['cooling_type'] == 'WaterCooled'
|
179
|
-
new_name = "#{props['cooling_type']} #{props['compressor_type']} Chiller"
|
180
|
-
else
|
181
|
-
new_name = chiller.name.get
|
182
|
-
end
|
183
|
-
chiller.setName(new_name)
|
184
|
-
|
185
|
-
# Apply the standard
|
186
|
-
std_applier.chiller_electric_eir_apply_efficiency_and_curves(chiller, nil)
|
187
|
-
|
188
|
-
# Reset the capacity
|
189
|
-
chiller.autosizeReferenceCapacity
|
190
|
-
|
191
|
-
# Modify the name of the chiller to reflect the capacity range
|
192
|
-
old_name = chiller.name.get.to_s
|
193
|
-
m = old_name.match(/(\d+)tons/)
|
194
|
-
if m
|
195
|
-
# Put the fuel type into the name
|
196
|
-
old_type = 'Chiller Electric EIR 1'
|
197
|
-
new_type = 'Chiller'
|
198
|
-
new_name = old_name.gsub(old_type, new_type)
|
199
|
-
# Swap out the capacity number for a range
|
200
|
-
old_cap = m[1]
|
201
|
-
if max_cap_tons == 10_000 # Value representing infinity
|
202
|
-
new_cap = "> #{min_cap_tons.round}"
|
203
|
-
else
|
204
|
-
new_cap = "#{min_cap_tons.round}-#{max_cap_tons.round}"
|
205
251
|
end
|
206
|
-
new_name = new_name.gsub(old_cap, new_cap)
|
207
|
-
chiller.setName(new_name)
|
208
|
-
puts "#{props['template']}: #{chiller.name.get.to_s}"
|
209
252
|
end
|
210
253
|
|
211
|
-
|
212
|
-
|
254
|
+
# Heat Pumps
|
255
|
+
if include_heat_pumps
|
256
|
+
puts "* Heat Pumps *"
|
257
|
+
std.standards_data['heat_pumps'].each do |props|
|
258
|
+
next unless props['template'] == template_name
|
259
|
+
|
260
|
+
# Skip interim efficiency requirements
|
261
|
+
next unless props['end_date'] == "2999-09-09T00:00:00+00:00"
|
262
|
+
|
263
|
+
# Make a new DX cooling coil
|
264
|
+
clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model)
|
265
|
+
# Set capacity to middle of range
|
266
|
+
min_clg_cap_btu_per_hr = props['minimum_capacity'].to_f
|
267
|
+
max_clg_cap_btu_per_hr = props['maximum_capacity'].to_f
|
268
|
+
mid_clg_cap_btu_per_hr = (min_clg_cap_btu_per_hr + max_clg_cap_btu_per_hr) / 2
|
269
|
+
mid_clg_cap_w = OpenStudio.convert(mid_clg_cap_btu_per_hr, 'Btu/hr', 'W').get
|
270
|
+
clg_coil.setRatedTotalCoolingCapacity(mid_clg_cap_w)
|
271
|
+
|
272
|
+
# Make a new DX heating coil sized at 90% of the capacity
|
273
|
+
# of the cooling coil.
|
274
|
+
htg_coil = OpenStudio::Model::CoilHeatingDXSingleSpeed.new(model)
|
275
|
+
mid_htg_cap_w = mid_clg_cap_w * 0.9
|
276
|
+
htg_coil.setRatedTotalHeatingCapacity(mid_htg_cap_w)
|
277
|
+
|
278
|
+
# If it is a PTHP Coil, add to PTHP
|
279
|
+
# If not, add to unitary HP
|
280
|
+
if props['subcategory'] == 'PTHP'
|
281
|
+
if props['heating_type'] == 'Electric Resistance or None'
|
282
|
+
backup_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model)
|
283
|
+
backup_htg_coil.setName('PTHP Electric Backup Htg Coil')
|
284
|
+
else
|
285
|
+
backup_htg_coil = OpenStudio::Model::CoilHeatingGas.new(model)
|
286
|
+
backup_htg_coil.setName('PTHP Electric Backup Htg Coil')
|
287
|
+
end
|
288
|
+
fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule)
|
289
|
+
fan.setName("PTHP Supply Fan")
|
290
|
+
pthp = OpenStudio::Model::ZoneHVACPackagedTerminalHeatPump.new(model,
|
291
|
+
model.alwaysOnDiscreteSchedule,
|
292
|
+
fan,
|
293
|
+
htg_coil,
|
294
|
+
clg_coil,
|
295
|
+
backup_htg_coil)
|
296
|
+
else
|
297
|
+
if props['heating_type'] == 'Electric Resistance or None'
|
298
|
+
backup_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model)
|
299
|
+
backup_htg_coil.setName('Unitary Heat Pump Electric Backup Htg Coil')
|
300
|
+
else
|
301
|
+
backup_htg_coil = OpenStudio::Model::CoilHeatingGas.new(model)
|
302
|
+
backup_htg_coil.setName('Unitary Heat Pump Electric Backup Htg Coil')
|
303
|
+
end
|
304
|
+
fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule)
|
305
|
+
fan.setName("Unitary Heat Pump Supply Fan")
|
306
|
+
unitary_system = OpenStudio::Model::AirLoopHVACUnitaryHeatPumpAirToAir.new(model,
|
307
|
+
model.alwaysOnDiscreteSchedule,
|
308
|
+
fan,
|
309
|
+
htg_coil,
|
310
|
+
clg_coil,
|
311
|
+
backup_htg_coil)
|
312
|
+
unitary_system.setName("Unitary Heat Pump")
|
313
|
+
unitary_system.setMaximumOutdoorDryBulbTemperatureforSupplementalHeaterOperation(OpenStudio.convert(40, 'F', 'C').get)
|
314
|
+
end
|
315
|
+
|
316
|
+
# Apply the standard
|
317
|
+
std_applier.coil_cooling_dx_single_speed_apply_efficiency_and_curves(clg_coil, {})
|
318
|
+
std_applier.coil_heating_dx_single_speed_apply_efficiency_and_curves(htg_coil, {})
|
319
|
+
|
320
|
+
# Reset the capacity
|
321
|
+
clg_coil.autosizeRatedTotalCoolingCapacity
|
322
|
+
htg_coil.autosizeRatedTotalHeatingCapacity
|
323
|
+
|
324
|
+
# Modify the name of the boiler to reflect the capacity range
|
325
|
+
min_clg_cap_kbtu_per_hr = OpenStudio.convert(min_clg_cap_btu_per_hr, 'Btu/hr', 'kBtu/hr').get.round
|
326
|
+
max_clg_cap_kbtu_per_hr = OpenStudio.convert(max_clg_cap_btu_per_hr, 'Btu/hr', 'kBtu/hr').get.round
|
327
|
+
|
328
|
+
# Modify the name of the dx_coil to reflect the capacity range
|
329
|
+
old_name = clg_coil.name.get.to_s
|
330
|
+
m = old_name.match(/(\d+)kBtu\/hr/)
|
331
|
+
if m
|
332
|
+
# Put the fuel type into the name
|
333
|
+
old_type = 'Coil Cooling DX Single Speed 1'
|
334
|
+
new_type = "#{props['cooling_type']} #{props['heating_type']} #{props['subcategory']} DX"
|
335
|
+
new_name = old_name.gsub(old_type, new_type)
|
336
|
+
# Swap out the capacity number for a range
|
337
|
+
old_cap = m[1]
|
338
|
+
if max_clg_cap_kbtu_per_hr == 10_000 # Value representing infinity
|
339
|
+
new_cap = "> #{min_clg_cap_kbtu_per_hr}"
|
340
|
+
else
|
341
|
+
new_cap = "#{min_clg_cap_kbtu_per_hr}-#{max_clg_cap_kbtu_per_hr}"
|
342
|
+
end
|
343
|
+
new_name = new_name.gsub(old_cap, new_cap)
|
344
|
+
clg_coil.setName(new_name)
|
345
|
+
puts "#{props['template']}: #{clg_coil.name.get.to_s}"
|
346
|
+
|
347
|
+
# Rename PTHP or unitary same as the cooling coil
|
348
|
+
if pthp
|
349
|
+
pthp.setName("PTHP #{new_name}")
|
350
|
+
else
|
351
|
+
unitary_system.setName("Unitary Heat Pump #{new_name}")
|
352
|
+
end
|
353
|
+
|
354
|
+
# Rename the heating coil
|
355
|
+
old_type = 'Coil Heating DX Single Speed 1'
|
356
|
+
new_type = "#{props['cooling_type']} #{props['heating_type']} #{props['subcategory']} DX"
|
357
|
+
new_name = old_name.gsub(old_type, new_type)
|
358
|
+
# Swap out the capacity number for a blank
|
359
|
+
old_cap = m[1]
|
360
|
+
new_name = new_name.gsub(old_cap, '')
|
361
|
+
htg_coil.setName(new_name)
|
362
|
+
|
363
|
+
end
|
213
364
|
|
214
|
-
# Unitary AC
|
215
|
-
if include_unitary_acs
|
216
|
-
std.standards_data['unitary_acs'].each do |props|
|
217
|
-
lib = template_to_lib_models[props['template']]
|
218
|
-
next if lib.nil? # Skip unsupported templates
|
219
|
-
# Skip NECB 2011 for now
|
220
|
-
next if props['template'] == 'NECB 2011'
|
221
|
-
model = lib['model']
|
222
|
-
std_applier = lib['standard_applier']
|
223
|
-
|
224
|
-
# Skip interim efficiency requirements
|
225
|
-
next unless props['end_date'] == "2999-09-09T00:00:00+00:00"
|
226
|
-
|
227
|
-
# Make a new DX coil
|
228
|
-
dx_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model)
|
229
|
-
# Set capacity to middle of range
|
230
|
-
min_cap_btu_per_hr = props['minimum_capacity'].to_f
|
231
|
-
max_cap_btu_per_hr = props['maximum_capacity'].to_f
|
232
|
-
mid_cap_btu_per_hr = (min_cap_btu_per_hr + max_cap_btu_per_hr) / 2
|
233
|
-
mid_cap_w = OpenStudio.convert(mid_cap_btu_per_hr, 'Btu/hr', 'W').get
|
234
|
-
dx_coil.setRatedTotalCoolingCapacity(mid_cap_w)
|
235
|
-
|
236
|
-
# Add the subcategory to the name so that it
|
237
|
-
# can be used by the efficiency lookup
|
238
|
-
dx_coil.setName("#{dx_coil.name} #{props['subcategory']}")
|
239
|
-
|
240
|
-
# If it is a PTAC coil, add to PTAC
|
241
|
-
if props['subcategory'] == 'PTAC'
|
242
|
-
htg_coil = nil
|
243
|
-
if props['heating_type'] == 'Electric Resistance or None'
|
244
|
-
htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model)
|
245
|
-
htg_coil.setName('PTAC Electric Backup Htg Coil')
|
246
|
-
else
|
247
|
-
htg_coil = OpenStudio::Model::CoilHeatingGas.new(model)
|
248
|
-
htg_coil.setName('PTAC Gas Backup Htg Coil')
|
249
365
|
end
|
250
|
-
fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule)
|
251
|
-
fan.setName("PTAC Supply Fan")
|
252
|
-
ptac = OpenStudio::Model::ZoneHVACPackagedTerminalAirConditioner.new(model,
|
253
|
-
model.alwaysOnDiscreteSchedule,
|
254
|
-
fan,
|
255
|
-
htg_coil,
|
256
|
-
dx_coil)
|
257
366
|
end
|
258
367
|
|
259
|
-
#
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
# Modify the name of the boiler to reflect the capacity range
|
266
|
-
min_cap_kbtu_per_hr = OpenStudio.convert(min_cap_btu_per_hr, 'Btu/hr', 'kBtu/hr').get.round
|
267
|
-
max_cap_kbtu_per_hr = OpenStudio.convert(max_cap_btu_per_hr, 'Btu/hr', 'kBtu/hr').get.round
|
268
|
-
|
269
|
-
# Modify the name of the dx_coil to reflect the capacity range
|
270
|
-
old_name = dx_coil.name.get.to_s
|
271
|
-
m = old_name.match(/(\d+)kBtu\/hr/)
|
272
|
-
if m
|
273
|
-
# Put the fuel type into the name
|
274
|
-
old_type = "Coil Cooling DX Single Speed 1 #{props['subcategory']}"
|
275
|
-
new_type = "#{props['cooling_type']} #{props['heating_type']} #{props['subcategory']} DX"
|
276
|
-
new_name = old_name.gsub(old_type, new_type)
|
277
|
-
# Swap out the capacity number for a range
|
278
|
-
old_cap = m[1]
|
279
|
-
if max_cap_kbtu_per_hr == 10_000 # Value representing infinity
|
280
|
-
new_cap = "> #{min_cap_kbtu_per_hr}"
|
281
|
-
else
|
282
|
-
new_cap = "#{min_cap_kbtu_per_hr}-#{max_cap_kbtu_per_hr}"
|
283
|
-
end
|
284
|
-
new_name = new_name.gsub(old_cap, new_cap)
|
285
|
-
dx_coil.setName(new_name)
|
286
|
-
puts "#{props['template']}: #{dx_coil.name.get.to_s}"
|
368
|
+
# Space Types
|
369
|
+
if include_space_types
|
370
|
+
puts "* Space Types *"
|
371
|
+
std.standards_data['space_types'].each do |props|
|
372
|
+
next unless props['template'] == template_name
|
287
373
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
374
|
+
# Create a new space type
|
375
|
+
space_type = OpenStudio::Model::SpaceType.new(model)
|
376
|
+
space_type.setStandardsBuildingType(props['building_type'])
|
377
|
+
space_type.setStandardsSpaceType(props['space_type'])
|
378
|
+
space_type.setName("#{props['building_type']} #{props['space_type']}")
|
292
379
|
|
293
|
-
|
380
|
+
# Rendering color
|
381
|
+
std_applier.space_type_apply_rendering_color(space_type)
|
294
382
|
|
295
|
-
|
296
|
-
|
383
|
+
# Loads
|
384
|
+
std_applier.space_type_apply_internal_loads(space_type, true, true, true, true, true, true)
|
385
|
+
|
386
|
+
# Schedules
|
387
|
+
std_applier.space_type_apply_internal_load_schedules(space_type, true, true, true, true, true, true, true)
|
297
388
|
|
298
|
-
# Heat Pumps
|
299
|
-
if include_heat_pumps
|
300
|
-
std.standards_data['heat_pumps'].each do |props|
|
301
|
-
lib = template_to_lib_models[props['template']]
|
302
|
-
next if lib.nil? # Skip unsupported templates
|
303
|
-
# Skip NECB 2011 for now
|
304
|
-
next if props['template'] == 'NECB 2011'
|
305
|
-
model = lib['model']
|
306
|
-
std_applier = lib['standard_applier']
|
307
|
-
|
308
|
-
# Skip interim efficiency requirements
|
309
|
-
next unless props['end_date'] == "2999-09-09T00:00:00+00:00"
|
310
|
-
|
311
|
-
# Make a new DX cooling coil
|
312
|
-
clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model)
|
313
|
-
# Set capacity to middle of range
|
314
|
-
min_clg_cap_btu_per_hr = props['minimum_capacity'].to_f
|
315
|
-
max_clg_cap_btu_per_hr = props['maximum_capacity'].to_f
|
316
|
-
mid_clg_cap_btu_per_hr = (min_clg_cap_btu_per_hr + max_clg_cap_btu_per_hr) / 2
|
317
|
-
mid_clg_cap_w = OpenStudio.convert(mid_clg_cap_btu_per_hr, 'Btu/hr', 'W').get
|
318
|
-
clg_coil.setRatedTotalCoolingCapacity(mid_clg_cap_w)
|
319
|
-
|
320
|
-
# Make a new DX heating coil sized at 90% of the capacity
|
321
|
-
# of the cooling coil.
|
322
|
-
htg_coil = OpenStudio::Model::CoilHeatingDXSingleSpeed.new(model)
|
323
|
-
mid_htg_cap_w = mid_clg_cap_w * 0.9
|
324
|
-
htg_coil.setRatedTotalHeatingCapacity(mid_htg_cap_w)
|
325
|
-
|
326
|
-
# If it is a PTHP Coil, add to PTHP
|
327
|
-
# If not, add to unitary HP
|
328
|
-
if props['subcategory'] == 'PTHP'
|
329
|
-
if props['heating_type'] == 'Electric Resistance or None'
|
330
|
-
backup_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model)
|
331
|
-
backup_htg_coil.setName('PTHP Electric Backup Htg Coil')
|
332
|
-
else
|
333
|
-
backup_htg_coil = OpenStudio::Model::CoilHeatingGas.new(model)
|
334
|
-
backup_htg_coil.setName('PTHP Electric Backup Htg Coil')
|
335
|
-
end
|
336
|
-
fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule)
|
337
|
-
fan.setName("PTHP Supply Fan")
|
338
|
-
pthp = OpenStudio::Model::ZoneHVACPackagedTerminalHeatPump.new(model,
|
339
|
-
model.alwaysOnDiscreteSchedule,
|
340
|
-
fan,
|
341
|
-
htg_coil,
|
342
|
-
clg_coil,
|
343
|
-
backup_htg_coil)
|
344
|
-
else
|
345
|
-
if props['heating_type'] == 'Electric Resistance or None'
|
346
|
-
backup_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model)
|
347
|
-
backup_htg_coil.setName('Unitary Heat Pump Electric Backup Htg Coil')
|
348
|
-
else
|
349
|
-
backup_htg_coil = OpenStudio::Model::CoilHeatingGas.new(model)
|
350
|
-
backup_htg_coil.setName('Unitary Heat Pump Electric Backup Htg Coil')
|
351
389
|
end
|
352
|
-
fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule)
|
353
|
-
fan.setName("Unitary Heat Pump Supply Fan")
|
354
|
-
unitary_system = OpenStudio::Model::AirLoopHVACUnitaryHeatPumpAirToAir.new(model,
|
355
|
-
model.alwaysOnDiscreteSchedule,
|
356
|
-
fan,
|
357
|
-
htg_coil,
|
358
|
-
clg_coil,
|
359
|
-
backup_htg_coil)
|
360
|
-
unitary_system.setName("Unitary Heat Pump")
|
361
|
-
unitary_system.setMaximumOutdoorDryBulbTemperatureforSupplementalHeaterOperation(OpenStudio.convert(40, 'F', 'C').get)
|
362
390
|
end
|
363
391
|
|
364
|
-
#
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
m = old_name.match(/(\d+)kBtu\/hr/)
|
379
|
-
if m
|
380
|
-
# Put the fuel type into the name
|
381
|
-
old_type = 'Coil Cooling DX Single Speed 1'
|
382
|
-
new_type = "#{props['cooling_type']} #{props['heating_type']} #{props['subcategory']} DX"
|
383
|
-
new_name = old_name.gsub(old_type, new_type)
|
384
|
-
# Swap out the capacity number for a range
|
385
|
-
old_cap = m[1]
|
386
|
-
if max_clg_cap_kbtu_per_hr == 10_000 # Value representing infinity
|
387
|
-
new_cap = "> #{min_clg_cap_kbtu_per_hr}"
|
388
|
-
else
|
389
|
-
new_cap = "#{min_clg_cap_kbtu_per_hr}-#{max_clg_cap_kbtu_per_hr}"
|
390
|
-
end
|
391
|
-
new_name = new_name.gsub(old_cap, new_cap)
|
392
|
-
clg_coil.setName(new_name)
|
393
|
-
puts "#{props['template']}: #{clg_coil.name.get.to_s}"
|
394
|
-
|
395
|
-
# Rename PTHP or unitary same as the cooling coil
|
396
|
-
if pthp
|
397
|
-
pthp.setName("PTHP #{new_name}")
|
398
|
-
else
|
399
|
-
unitary_system.setName("Unitary Heat Pump #{new_name}")
|
392
|
+
# Construction Sets, Constructions, and Materials
|
393
|
+
# TODO fix code to remove duplicate constructions and materials
|
394
|
+
if include_construction_sets
|
395
|
+
puts "* Construction Sets *"
|
396
|
+
std.standards_data['construction_sets'].each do |props|
|
397
|
+
next unless props['template'] == template_name
|
398
|
+
# Add a construction set for each valid climate zone
|
399
|
+
templates_to_climate_zones[props['template']].each do |climate_zone|
|
400
|
+
construction_set = std_applier.model_add_construction_set(model,
|
401
|
+
climate_zone,
|
402
|
+
props['building_type'],
|
403
|
+
props['space_type'],
|
404
|
+
props['is_residential'])
|
405
|
+
end
|
400
406
|
end
|
407
|
+
end
|
401
408
|
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
htg_coil.setName(new_name)
|
410
|
-
|
409
|
+
# Delete all the unused curves
|
410
|
+
puts '* Cleaning up the unused curves *'
|
411
|
+
model.getCurves.sort.each do |curve|
|
412
|
+
if curve.directUseCount == 0
|
413
|
+
puts " #{curve.name} is unused; successfully removed? #{model.removeObject(curve.handle)}."
|
414
|
+
# curve.remove # For some reason curve.remove doesn't work properly
|
415
|
+
end
|
411
416
|
end
|
412
417
|
|
418
|
+
# Save the library
|
419
|
+
osm_lib_dir = "#{__dir__}/../../pkg/libraries"
|
420
|
+
Dir.mkdir(osm_lib_dir) unless Dir.exists?(osm_lib_dir)
|
421
|
+
library_path = "#{osm_lib_dir}/#{template_name.gsub(/\W/,'_')}.osm"
|
422
|
+
puts "* Saving library #{library_path}"
|
423
|
+
model.save(OpenStudio::Path.new(library_path), true)
|
424
|
+
|
425
|
+
# Save the log messages for debugging library creation
|
426
|
+
log_path = "#{osm_lib_dir}/#{template_name.gsub(/\W/,'_')}.log"
|
427
|
+
puts "* Saving log #{log_path}"
|
428
|
+
log_messages_to_file(log_path, debug=false)
|
429
|
+
|
430
|
+
# Show the timing
|
431
|
+
template_end_time = Time.now
|
432
|
+
template_time_min = ((template_end_time - template_start_time)/60.0).round(1)
|
433
|
+
puts "* Finished #{template_name} at: #{template_end_time}, time elapsed = #{template_time_min} min."
|
434
|
+
|
435
|
+
rescue Exception => exc
|
436
|
+
puts "ERROR creating '#{template_name}', skipping to next template."
|
437
|
+
puts "#{exc}"
|
438
|
+
puts "Backtrace:\n\t#{e.caller.join("\n\t")}"
|
439
|
+
puts "Backtrace:\n\t#{e.backtrace.join("\n\t")}"
|
440
|
+
|
441
|
+
# Save the log messages for debugging library creation even on failure
|
442
|
+
log_path = "#{osm_lib_dir}/#{template_name.gsub(/\W/,'_')}.log"
|
443
|
+
puts "* Saving log #{log_path}"
|
444
|
+
log_messages_to_file(log_path, debug=false)
|
413
445
|
end
|
414
|
-
end
|
415
446
|
|
416
|
-
# Delete all the unused curves
|
417
|
-
puts 'Cleaning up the unused curves'
|
418
|
-
template_to_lib_models.each do |template, data|
|
419
|
-
puts ''
|
420
|
-
puts "***#{template}***"
|
421
|
-
data['model'].getCurves.sort.each do |curve|
|
422
|
-
if curve.directUseCount == 0
|
423
|
-
puts " #{curve.name} is unused; successfully removed? #{data['model'].removeObject(curve.handle)}."
|
424
|
-
# curve.remove # For some reason curve.remove doesn't work properly
|
425
|
-
end
|
426
|
-
end
|
427
447
|
end
|
428
448
|
|
429
|
-
#
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
library_path = "#{osm_lib_dir}/#{template.gsub(/\W/,'_')}.osm"
|
434
|
-
puts "Saving library #{library_path}"
|
435
|
-
data['model'].save(OpenStudio::Path.new(library_path), true)
|
436
|
-
end
|
449
|
+
# Show the timing
|
450
|
+
end_time = Time.now
|
451
|
+
total_time_min = ((end_time - start_time)/60.0).round(1)
|
452
|
+
puts "*** Finished all templates at: #{end_time}, time elapsed = #{total_time_min} min."
|
437
453
|
|
438
454
|
end
|
@@ -71,8 +71,8 @@ module Hospital
|
|
71
71
|
elec_equip_def1.setDesignLevel(915)
|
72
72
|
elec_equip_def2.setDesignLevel(855)
|
73
73
|
else
|
74
|
-
elec_equip_def1.setDesignLevel(
|
75
|
-
elec_equip_def2.setDesignLevel(
|
74
|
+
elec_equip_def1.setDesignLevel(915)
|
75
|
+
elec_equip_def2.setDesignLevel(855)
|
76
76
|
end
|
77
77
|
# Create the electric equipment instance and hook it up to the space type
|
78
78
|
elec_equip1 = OpenStudio::Model::ElectricEquipment.new(elec_equip_def1)
|
@@ -106,8 +106,8 @@ module LargeHotel
|
|
106
106
|
elec_equip_def1.setDesignLevel(457.7)
|
107
107
|
elec_equip_def2.setDesignLevel(285)
|
108
108
|
else
|
109
|
-
elec_equip_def1.setDesignLevel(
|
110
|
-
elec_equip_def2.setDesignLevel(
|
109
|
+
elec_equip_def1.setDesignLevel(457.7)
|
110
|
+
elec_equip_def2.setDesignLevel(285)
|
111
111
|
end
|
112
112
|
# Create the electric equipment instance and hook it up to the space type
|
113
113
|
elec_equip1 = OpenStudio::Model::ElectricEquipment.new(elec_equip_def1)
|
@@ -33,8 +33,8 @@ module PrimarySchool
|
|
33
33
|
elec_equip_def1.setDesignLevel(915)
|
34
34
|
elec_equip_def2.setDesignLevel(570)
|
35
35
|
else
|
36
|
-
elec_equip_def1.setDesignLevel(
|
37
|
-
elec_equip_def2.setDesignLevel(
|
36
|
+
elec_equip_def1.setDesignLevel(1032)
|
37
|
+
elec_equip_def2.setDesignLevel(852)
|
38
38
|
end
|
39
39
|
# Create the electric equipment instance and hook it up to the space type
|
40
40
|
elec_equip1 = OpenStudio::Model::ElectricEquipment.new(elec_equip_def1)
|
@@ -49,8 +49,8 @@ module SecondarySchool
|
|
49
49
|
elec_equip_def1.setDesignLevel(915)
|
50
50
|
elec_equip_def2.setDesignLevel(570)
|
51
51
|
else
|
52
|
-
elec_equip_def1.setDesignLevel(
|
53
|
-
elec_equip_def2.setDesignLevel(
|
52
|
+
elec_equip_def1.setDesignLevel(1032)
|
53
|
+
elec_equip_def2.setDesignLevel(852)
|
54
54
|
end
|
55
55
|
# Create the electric equipment instance and hook it up to the space type
|
56
56
|
elec_equip1 = OpenStudio::Model::ElectricEquipment.new(elec_equip_def1)
|
@@ -78,4 +78,17 @@ module References
|
|
78
78
|
# @see http://deeresources.com/index.php/deer-versions
|
79
79
|
class DEERMASControl; end
|
80
80
|
|
81
|
+
# OEESC 2014
|
82
|
+
# The Oregon Energy Efficiency Specialty Code is the building energy code for the
|
83
|
+
# state of Oregon. It is very similar to ASHRAE 90.1-2013, but has been tailored
|
84
|
+
# to meet the needs of Oregon.
|
85
|
+
# @see http://www.oregon.gov/bcd/codes-stand/Pages/energy-efficiency.aspx
|
86
|
+
class OEESC2014; end
|
87
|
+
|
88
|
+
# ICC IECC 2015
|
89
|
+
# The International Code Council's International Energy Conservation Code is widely
|
90
|
+
# used across the United States.
|
91
|
+
# @see https://codes.iccsafe.org/public/document/toc/545/
|
92
|
+
class ICCIECC2015; end
|
93
|
+
|
81
94
|
end
|
@@ -265,7 +265,7 @@ class Standard
|
|
265
265
|
# Only applies to fenestration constructions.
|
266
266
|
# @return [Double] the SHGC as a decimal.
|
267
267
|
def construction_calculated_solar_heat_gain_coefficient(construction)
|
268
|
-
construction_name = name.get.to_s
|
268
|
+
construction_name = construction.name.get.to_s
|
269
269
|
|
270
270
|
shgc = nil
|
271
271
|
|
@@ -286,7 +286,7 @@ class Standard
|
|
286
286
|
if row_id.is_initialized
|
287
287
|
row_id = row_id.get
|
288
288
|
else
|
289
|
-
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.model.
|
289
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.model.Construction', "SHGC row ID not found for construction: #{construction_name}.")
|
290
290
|
row_id = 9999
|
291
291
|
end
|
292
292
|
|
@@ -315,7 +315,7 @@ class Standard
|
|
315
315
|
# Only applies to fenestration constructions.
|
316
316
|
# @return [Double] the visible transmittance as a decimal.
|
317
317
|
def construction_calculated_visible_transmittance(construction)
|
318
|
-
construction_name = name.get.to_s
|
318
|
+
construction_name = construction.name.get.to_s
|
319
319
|
|
320
320
|
vt = nil
|
321
321
|
|
@@ -365,7 +365,7 @@ class Standard
|
|
365
365
|
# Only applies to fenestration constructions.
|
366
366
|
# @return [Double] the U-Factor in W/m^2*K.
|
367
367
|
def construction_calculated_u_factor(construction)
|
368
|
-
construction_name = name.get.to_s
|
368
|
+
construction_name = construction.name.get.to_s
|
369
369
|
|
370
370
|
u_factor_w_per_m2_k = nil
|
371
371
|
|
@@ -386,7 +386,7 @@ class Standard
|
|
386
386
|
if row_id.is_initialized
|
387
387
|
row_id = row_id.get
|
388
388
|
else
|
389
|
-
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.model.
|
389
|
+
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.model.Construction', "U-Factor row ID not found for construction: #{construction_name}.")
|
390
390
|
row_id = 9999
|
391
391
|
end
|
392
392
|
|
@@ -405,7 +405,7 @@ class Standard
|
|
405
405
|
end
|
406
406
|
|
407
407
|
else
|
408
|
-
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.
|
408
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Construction', 'Model has no sql file containing results, cannot lookup data.')
|
409
409
|
end
|
410
410
|
|
411
411
|
return u_factor_w_per_m2_k
|
@@ -278,13 +278,24 @@ module Pump
|
|
278
278
|
end
|
279
279
|
|
280
280
|
rated_m3_per_s = 0
|
281
|
-
if pump.
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
281
|
+
if pump.to_PumpVariableSpeed.is_initialized || pump.to_PumpConstantSpeed.is_initialized
|
282
|
+
if pump.ratedFlowRate.is_initialized
|
283
|
+
rated_m3_per_s = pump.ratedFlowRate.get
|
284
|
+
elsif pump.autosizedRatedFlowRate.is_initialized
|
285
|
+
rated_m3_per_s = pump.autosizedRatedFlowRate.get
|
286
|
+
else
|
287
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Pump', "For #{pump.name}, could not find rated pump Flow Rate, cannot determine w per gpm correctly.")
|
288
|
+
return 0.0
|
289
|
+
end
|
290
|
+
elsif pump.to_HeaderedPumpsVariableSpeed.is_initialized || pump.to_HeaderedPumpsConstantSpeed.is_initialized
|
291
|
+
if pump.totalRatedFlowRate.is_initialized
|
292
|
+
rated_m3_per_s = pump.totalRatedFlowRate.get
|
293
|
+
elsif pump.autosizedTotalRatedFlowRate.is_initialized
|
294
|
+
rated_m3_per_s = pump.autosizedTotalRatedFlowRate.get
|
295
|
+
else
|
296
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Pump', "For #{pump.name}, could not find rated pump Flow Rate, cannot determine w per gpm correctly.")
|
297
|
+
return 0.0
|
298
|
+
end
|
288
299
|
end
|
289
300
|
|
290
301
|
rated_w_per_m3s = rated_power_w / rated_m3_per_s
|
@@ -79,7 +79,7 @@ class Standard
|
|
79
79
|
|
80
80
|
previous_time_decimal = 0
|
81
81
|
times.each_with_index do |time, i|
|
82
|
-
time_decimal = (time.days * 24) + time.hours + (time.minutes / 60) + (time.seconds / 3600)
|
82
|
+
time_decimal = (time.days * 24.0) + time.hours + (time.minutes / 60.0) + (time.seconds / 3600.0)
|
83
83
|
duration_of_value = time_decimal - previous_time_decimal
|
84
84
|
# OpenStudio::logFree(OpenStudio::Debug, "openstudio.standards.ScheduleRuleset", " Value of #{values[i]} for #{duration_of_value} hours")
|
85
85
|
daily_flh += values[i] * duration_of_value
|
@@ -219,7 +219,7 @@ class Standard
|
|
219
219
|
|
220
220
|
previous_time_decimal = 0
|
221
221
|
times.each_with_index do |time, i|
|
222
|
-
time_decimal = (time.days * 24) + time.hours + (time.minutes / 60) + (time.seconds / 3600)
|
222
|
+
time_decimal = (time.days * 24.0) + time.hours + (time.minutes / 60.0) + (time.seconds / 3600.0)
|
223
223
|
duration_of_value = time_decimal - previous_time_decimal
|
224
224
|
# OpenStudio::logFree(OpenStudio::Debug, "openstudio.standards.ScheduleRuleset", " Value of #{values[i]} for #{duration_of_value} hours")
|
225
225
|
daily_hrs += values[i] * duration_of_value
|
@@ -396,7 +396,7 @@ class Standard
|
|
396
396
|
# Electricity, NaturalGas, PropaneGas, FuelOil#1, FuelOil#2,
|
397
397
|
# Coal, Diesel, Gasoline, DistrictHeating,
|
398
398
|
# and SolarEnergy.
|
399
|
-
htg_fuels = heating_fuels
|
399
|
+
htg_fuels = thermal_zone.heating_fuels
|
400
400
|
|
401
401
|
if htg_fuels.include?('NaturalGas') ||
|
402
402
|
htg_fuels.include?('PropaneGas') ||
|
@@ -498,7 +498,7 @@ class Standard
|
|
498
498
|
# Electricity, NaturalGas, PropaneGas, FuelOil#1, FuelOil#2,
|
499
499
|
# Coal, Diesel, Gasoline, DistrictHeating,
|
500
500
|
# and SolarEnergy.
|
501
|
-
htg_fuels = heating_fuels
|
501
|
+
htg_fuels = thermal_zone.heating_fuels
|
502
502
|
|
503
503
|
# Includes fossil
|
504
504
|
fossil = false
|
@@ -576,7 +576,7 @@ class Standard
|
|
576
576
|
has_ptac = false
|
577
577
|
has_pthp = false
|
578
578
|
has_unitheater = false
|
579
|
-
equipment.each do |equip|
|
579
|
+
thermal_zone.equipment.each do |equip|
|
580
580
|
# Skip HVAC components
|
581
581
|
next unless equip.to_HVACComponent.is_initialized
|
582
582
|
equip = equip.to_HVACComponent.get
|
@@ -601,8 +601,8 @@ class Standard
|
|
601
601
|
end
|
602
602
|
|
603
603
|
# Get the zone heating and cooling fuels
|
604
|
-
htg_fuels = heating_fuels
|
605
|
-
clg_fuels = cooling_fuels
|
604
|
+
htg_fuels = thermal_zone.heating_fuels
|
605
|
+
clg_fuels = thermal_zone.cooling_fuels
|
606
606
|
is_fossil = thermal_zone_fossil_hybrid_or_purchased_heat?(thermal_zone)
|
607
607
|
|
608
608
|
# Infer the HVAC type
|
@@ -615,7 +615,7 @@ class Standard
|
|
615
615
|
# Air Loop
|
616
616
|
if has_air_loop
|
617
617
|
# Gas_Furnace (as air loop)
|
618
|
-
sys_type = if
|
618
|
+
sys_type = if clg_fuels.size.zero?
|
619
619
|
'Gas_Furnace'
|
620
620
|
# PSZ_AC
|
621
621
|
else
|
@@ -637,7 +637,7 @@ class Standard
|
|
637
637
|
# Air Loop
|
638
638
|
if has_air_loop
|
639
639
|
# Electric_Furnace (as air loop)
|
640
|
-
sys_type = if
|
640
|
+
sys_type = if clg_fuels.size.zero?
|
641
641
|
'Electric_Furnace'
|
642
642
|
# PSZ_HP
|
643
643
|
else
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# This class will hold methods that apply ICC IECC 2015
|
2
|
+
# to a given model.
|
3
|
+
# @todo ICC IECC 2015 is incomplete and will default to the logic
|
4
|
+
# in the default Standard class methods
|
5
|
+
# @ref [References::ICCIECC2015]
|
6
|
+
class ICCIECC2015 < ICCIECC
|
7
|
+
@@template = 'ICC IECC 2015' # rubocop:disable Style/ClassVars
|
8
|
+
register_standard @@template
|
9
|
+
attr_reader :template
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
super()
|
13
|
+
@template = @@template
|
14
|
+
load_standards_database
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# This class will hold methods that apply OEESC 2014
|
2
|
+
# to a given model.
|
3
|
+
# @todo OEESC 2014 is incomplete and will default to the logic
|
4
|
+
# in the default Standard class methods
|
5
|
+
# @ref [References::OEESC2014]
|
6
|
+
class OEESC2014 < OEESC
|
7
|
+
@@template = 'OEESC 2014' # rubocop:disable Style/ClassVars
|
8
|
+
register_standard @@template
|
9
|
+
attr_reader :template
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
super()
|
13
|
+
@template = @@template
|
14
|
+
load_standards_database
|
15
|
+
end
|
16
|
+
end
|
data/lib/openstudio-standards.rb
CHANGED
@@ -85,6 +85,12 @@ module OpenstudioStandards
|
|
85
85
|
require_relative "#{stds}/deer/deer_2015/deer_2015"
|
86
86
|
require_relative "#{stds}/deer/deer_2017/deer_2017"
|
87
87
|
|
88
|
+
require_relative "#{stds}/oeesc/oeesc"
|
89
|
+
require_relative "#{stds}/oeesc/oeesc_2014/oeesc_2014"
|
90
|
+
|
91
|
+
require_relative "#{stds}/icc_iecc/icc_iecc"
|
92
|
+
require_relative "#{stds}/icc_iecc/icc_iecc_2015/icc_iecc_2015"
|
93
|
+
|
88
94
|
# Files with modules
|
89
95
|
require_relative "#{stds}/Standards.Fan"
|
90
96
|
require_relative "#{stds}/Standards.CoilDX"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openstudio-standards
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.0.
|
4
|
+
version: 0.2.0.rc2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Parker
|
@@ -21,7 +21,7 @@ authors:
|
|
21
21
|
autorequire:
|
22
22
|
bindir: bin
|
23
23
|
cert_chain: []
|
24
|
-
date: 2018-
|
24
|
+
date: 2018-03-16 00:00:00.000000000 Z
|
25
25
|
dependencies:
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: minitest-reporters
|
@@ -141,14 +141,14 @@ dependencies:
|
|
141
141
|
requirements:
|
142
142
|
- - "~>"
|
143
143
|
- !ruby/object:Gem::Version
|
144
|
-
version: '0.
|
144
|
+
version: '0.53'
|
145
145
|
type: :development
|
146
146
|
prerelease: false
|
147
147
|
version_requirements: !ruby/object:Gem::Requirement
|
148
148
|
requirements:
|
149
149
|
- - "~>"
|
150
150
|
- !ruby/object:Gem::Version
|
151
|
-
version: '0.
|
151
|
+
version: '0.53'
|
152
152
|
- !ruby/object:Gem::Dependency
|
153
153
|
name: rubocop-checkstyle_formatter
|
154
154
|
requirement: !ruby/object:Gem::Requirement
|
@@ -1560,6 +1560,8 @@ files:
|
|
1560
1560
|
- lib/openstudio-standards/standards/deer/deer_2015/deer_2015.rb
|
1561
1561
|
- lib/openstudio-standards/standards/deer/deer_2017/deer_2017.rb
|
1562
1562
|
- lib/openstudio-standards/standards/deer/deer_pre_1975/deer_pre_1975.rb
|
1563
|
+
- lib/openstudio-standards/standards/icc_iecc/icc_iecc.rb
|
1564
|
+
- lib/openstudio-standards/standards/icc_iecc/icc_iecc_2015/icc_iecc_2015.rb
|
1563
1565
|
- lib/openstudio-standards/standards/necb/necb_2011/beps_compliance_path.rb
|
1564
1566
|
- lib/openstudio-standards/standards/necb/necb_2011/building_envelope.rb
|
1565
1567
|
- lib/openstudio-standards/standards/necb/necb_2011/data/boilers.json
|
@@ -1592,6 +1594,8 @@ files:
|
|
1592
1594
|
- lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb
|
1593
1595
|
- lib/openstudio-standards/standards/necb/necb_2011/service_water_heating.rb
|
1594
1596
|
- lib/openstudio-standards/standards/necb/necb_2015/necb_2015.rb
|
1597
|
+
- lib/openstudio-standards/standards/oeesc/oeesc.rb
|
1598
|
+
- lib/openstudio-standards/standards/oeesc/oeesc_2014/oeesc_2014.rb
|
1595
1599
|
- lib/openstudio-standards/standards/standard.rb
|
1596
1600
|
- lib/openstudio-standards/utilities/convert_costing_constructions.rb
|
1597
1601
|
- lib/openstudio-standards/utilities/define_thermal_zone_and_mulitpliers.rb
|