openstudio-standards 0.2.0.rc1 → 0.2.0.rc2

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.
Files changed (23) hide show
  1. checksums.yaml +4 -4
  2. data/data/standards/export_OpenStudio_libraries.rb +392 -376
  3. data/data/standards/manage_OpenStudio_Standards.rb +0 -1
  4. data/lib/openstudio-standards/btap/fileio.rb +0 -1
  5. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Hospital.rb +2 -2
  6. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeHotel.rb +2 -2
  7. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.PrimarySchool.rb +2 -2
  8. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SecondarySchool.rb +2 -2
  9. data/lib/openstudio-standards/refs/references.rb +13 -0
  10. data/lib/openstudio-standards/standards/Standards.Construction.rb +6 -6
  11. data/lib/openstudio-standards/standards/Standards.Model.rb +1 -1
  12. data/lib/openstudio-standards/standards/Standards.Pump.rb +18 -7
  13. data/lib/openstudio-standards/standards/Standards.ScheduleRuleset.rb +2 -2
  14. data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +7 -7
  15. data/lib/openstudio-standards/standards/icc_iecc/icc_iecc.rb +9 -0
  16. data/lib/openstudio-standards/standards/icc_iecc/icc_iecc_2015/icc_iecc_2015.rb +16 -0
  17. data/lib/openstudio-standards/standards/necb/necb_2011/necb_2011.rb +0 -1
  18. data/lib/openstudio-standards/standards/necb/necb_2015/necb_2015.rb +0 -1
  19. data/lib/openstudio-standards/standards/oeesc/oeesc.rb +9 -0
  20. data/lib/openstudio-standards/standards/oeesc/oeesc_2014/oeesc_2014.rb +16 -0
  21. data/lib/openstudio-standards/version.rb +1 -1
  22. data/lib/openstudio-standards.rb +6 -0
  23. metadata +8 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a78c7667ff57212581bbc69d8744490c265aff07
4
- data.tar.gz: b107d9d448db0c835b05bacb73ba5bc56ca3d51b
3
+ metadata.gz: 7971c760a2256abb5458a28ad4e0d31a9364acca
4
+ data.tar.gz: b4ed3ac1b33749ad8511de8b22dac45052074476
5
5
  SHA512:
6
- metadata.gz: 27fa35de23af880319a26fff22651e1f537eb552fda5a94a09f2a47fd4c5eed354138993b5eb90cdb6621b6b7cd146f721f751dd0441d15df71b036f272d6b5b
7
- data.tar.gz: d15cce110d43968f18d4374b3b3144606c3b1aabb88f1ee328431e2ccfee4b2b4f50b72621a2817dd123f9fb4bb89bf0da0478934a500a4aad5b2a79d0529e40
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 = true # CoilCoolingDXSingleSpeed, CoilHeatingDXSingleSpeed, AirLoopHVACUnitaryHeatPump
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
- template_name = template['name']
33
- data = {}
34
- data['model'] = OpenStudio::Model::Model.new
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
- # Construction Sets, Constructions, and Materials
44
- # TODO fix code to remove duplicate constructions and materials
45
- if include_construction_sets
46
- std.standards_data['construction_sets'].each do |props|
47
- lib = template_to_lib_models[props['template']]
48
- next if lib.nil? # Skip unsupported templates
49
- model = lib['model']
50
- std_applier = lib['standard_applier']
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
- # Create a new space type
72
- space_type = OpenStudio::Model::SpaceType.new(model)
73
- space_type.setStandardsBuildingType(props['building_type'])
74
- space_type.setStandardsSpaceType(props['space_type'])
75
- space_type.setName("#{props['building_type']} #{props['space_type']}")
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
- # Rendering color
78
- std_applier.space_type_apply_rendering_color(space_type)
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
- # Schedules
84
- std_applier.space_type_apply_internal_load_schedules(space_type, true, true, true, true, true, true, true)
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
- end
147
- end
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
- end
212
- end
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
- # Apply the standard
260
- std_applier.coil_cooling_dx_single_speed_apply_efficiency_and_curves(dx_coil, {})
261
-
262
- # Reset the capacity
263
- dx_coil.autosizeRatedTotalCoolingCapacity
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
- # Rename PTAC too
289
- if props['subcategory'] == 'PTAC'
290
- ptac.setName("PTAC #{new_name}")
291
- end
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
- end
380
+ # Rendering color
381
+ std_applier.space_type_apply_rendering_color(space_type)
294
382
 
295
- end
296
- end
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
- # Apply the standard
365
- std_applier.coil_cooling_dx_single_speed_apply_efficiency_and_curves(clg_coil, {})
366
- std_applier.coil_heating_dx_single_speed_apply_efficiency_and_curves(htg_coil, {})
367
-
368
- # Reset the capacity
369
- clg_coil.autosizeRatedTotalCoolingCapacity
370
- htg_coil.autosizeRatedTotalHeatingCapacity
371
-
372
- # Modify the name of the boiler to reflect the capacity range
373
- min_clg_cap_kbtu_per_hr = OpenStudio.convert(min_clg_cap_btu_per_hr, 'Btu/hr', 'kBtu/hr').get.round
374
- max_clg_cap_kbtu_per_hr = OpenStudio.convert(max_clg_cap_btu_per_hr, 'Btu/hr', 'kBtu/hr').get.round
375
-
376
- # Modify the name of the dx_coil to reflect the capacity range
377
- old_name = clg_coil.name.get.to_s
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
- # Rename the heating coil
403
- old_type = 'Coil Heating DX Single Speed 1'
404
- new_type = "#{props['cooling_type']} #{props['heating_type']} #{props['subcategory']} DX"
405
- new_name = old_name.gsub(old_type, new_type)
406
- # Swap out the capacity number for a blank
407
- old_cap = m[1]
408
- new_name = new_name.gsub(old_cap, '')
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
- # Save the libraries
430
- osm_lib_dir = "#{__dir__}/../../pkg/libraries"
431
- Dir.mkdir(osm_lib_dir) unless Dir.exists?(osm_lib_dir)
432
- template_to_lib_models.each do |template, data|
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
@@ -1,7 +1,6 @@
1
1
  # This script reads OpenStudio_standards.xlsx
2
2
  # and creates a JSON file containing all the information
3
3
 
4
- require 'rubygems'
5
4
  require 'json'
6
5
  require 'rubyXL'
7
6
 
@@ -22,7 +22,6 @@ require "#{File.dirname(__FILE__)}/btap"
22
22
  require 'fileutils'
23
23
  require 'csv'
24
24
  require 'securerandom'
25
- #require 'rubygems'
26
25
 
27
26
 
28
27
  module BTAP
@@ -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(99_999.88)
75
- elec_equip_def2.setDesignLevel(99_999.99)
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(99_999.88)
110
- elec_equip_def2.setDesignLevel(99_999.99)
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(99_999.88)
37
- elec_equip_def2.setDesignLevel(99_999.99)
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(99_999.88)
53
- elec_equip_def2.setDesignLevel(99_999.99)
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.Model', "SHGC row ID not found for construction: #{construction_name}.")
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.Model', "U-Factor row ID not found for construction: #{construction_name}.")
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.Space', 'Model has no sql file containing results, cannot lookup data.')
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
@@ -4011,7 +4011,7 @@ class Standard
4011
4011
 
4012
4012
  parts = [template]
4013
4013
 
4014
- unless building_type.empty?
4014
+ unless building_type.nil?
4015
4015
  parts << building_type
4016
4016
  end
4017
4017
 
@@ -278,13 +278,24 @@ module Pump
278
278
  end
279
279
 
280
280
  rated_m3_per_s = 0
281
- if pump.autosizedRatedFlowRate.is_initialized
282
- rated_m3_per_s = pump.autosizedRatedFlowRate.get
283
- elsif pump.ratedFlowRate.is_initialized
284
- rated_m3_per_s = pump.ratedFlowRate.get
285
- else
286
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Pump', "For #{pump.name}, could not find rated pump Flow Rate, cannot determine w per gpm correctly.")
287
- return 0.0
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 cooling_fuels.size.zero?
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 cooling_fuels.size.zero?
640
+ sys_type = if clg_fuels.size.zero?
641
641
  'Electric_Furnace'
642
642
  # PSZ_HP
643
643
  else
@@ -0,0 +1,9 @@
1
+ # This abstract class holds methods that many versions of ICC IECC share.
2
+ # If a method in this class is redefined by a subclass,
3
+ # the implementation in the subclass is used.
4
+ # @abstract
5
+ class ICCIECC < Standard
6
+ def initialize
7
+ super()
8
+ end
9
+ end
@@ -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
@@ -1,6 +1,5 @@
1
1
  # This class holds methods that apply NECB2011 rules.
2
2
  # @ref [References::NECB2011]
3
- require 'rubyXL'
4
3
  class NECB2011 < Standard
5
4
  @template = self.new.class.name # rubocop:disable Style/ClassVars
6
5
  register_standard(@template)
@@ -1,6 +1,5 @@
1
1
  # This class holds methods that apply NECB2011 rules.
2
2
  # @ref [References::NECB2011]
3
- require 'rubyXL'
4
3
  class NECB2015 < NECB2011
5
4
  @template = self.new.class.name # rubocop:disable Style/ClassVars
6
5
  register_standard(@template)
@@ -0,0 +1,9 @@
1
+ # This abstract class holds methods that many versions of OEESC share.
2
+ # If a method in this class is redefined by a subclass,
3
+ # the implementation in the subclass is used.
4
+ # @abstract
5
+ class OEESC < Standard
6
+ def initialize
7
+ super()
8
+ end
9
+ 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
@@ -13,5 +13,5 @@ module OpenstudioStandards
13
13
  end
14
14
  return 'git-not-found-on-this-system'
15
15
  end
16
- VERSION = '0.2.0.rc1'.freeze
16
+ VERSION = '0.2.0.rc2'.freeze
17
17
  end
@@ -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.rc1
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-02-17 00:00:00.000000000 Z
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.50'
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.50'
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