openstudio-standards 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openstudio-standards/exterior_lighting/create.rb +2 -2
  3. data/lib/openstudio-standards/exterior_lighting/data/convert_entryway_data.rb +94 -0
  4. data/lib/openstudio-standards/exterior_lighting/data/convert_parking_data.rb +82 -0
  5. data/lib/openstudio-standards/exterior_lighting/data/entryways.json +565 -0
  6. data/lib/openstudio-standards/exterior_lighting/data/parking.json +428 -0
  7. data/lib/openstudio-standards/exterior_lighting/information.rb +14 -14
  8. data/lib/openstudio-standards/hvac/components/create.rb +4 -4
  9. data/lib/openstudio-standards/hvac/components/modify.rb +2 -2
  10. data/lib/openstudio-standards/hvac/exhaust/create_exhaust_fan.rb +2 -2
  11. data/lib/openstudio-standards/hvac/exhaust/data/convert_typical_exhaust_data.rb +67 -0
  12. data/lib/openstudio-standards/infiltration/data/NISTInfiltrationCorrelations.json +3172 -0
  13. data/lib/openstudio-standards/infiltration/data/convert_infiltration_data.rb +87 -0
  14. data/lib/openstudio-standards/infiltration/infiltration.rb +3 -3
  15. data/lib/openstudio-standards/infiltration/nist_infiltration.rb +42 -42
  16. data/lib/openstudio-standards/refrigeration/create_case.rb +2 -2
  17. data/lib/openstudio-standards/refrigeration/create_typical_refrigeration.rb +22 -21
  18. data/lib/openstudio-standards/service_water_heating/create_typical.rb +1 -1
  19. data/lib/openstudio-standards/standards/Standards.Space.rb +3 -0
  20. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirLoopHVAC.rb +10 -2
  21. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.schedules.json +131 -107
  22. data/lib/openstudio-standards/standards/deer/data/deer.schedules.json +24 -24
  23. data/lib/openstudio-standards/utilities/ruleset_check.rb +1 -2
  24. data/lib/openstudio-standards/version.rb +1 -1
  25. data/lib/openstudio-standards/weather/stat_file.rb +13 -4
  26. metadata +9 -3
  27. data/lib/openstudio-standards/hvac/exhaust/data/convert_data.rb +0 -86
@@ -0,0 +1,87 @@
1
+ # These methods convert infiltration data to and from .csv for editing.
2
+ private
3
+
4
+ require 'csv'
5
+ require 'json'
6
+
7
+ def infiltration_csv_to_json(input_csv = 'NISTInfiltrationCorrelations.csv',
8
+ output_json = 'NISTInfiltrationCorrelations.json')
9
+ # Initialize the structure
10
+ result = {
11
+ infiltration: []
12
+ }
13
+
14
+ # Read the CSV file
15
+ CSV.foreach(input_csv, headers: true, header_converters: :symbol) do |row|
16
+ building_type = row[:building_type]
17
+ climate_zone = row[:climate_zone]
18
+ air_barrier = row[:air_barrier]
19
+ hvac_status = row[:hvac_status]
20
+ a = row[:a]&.to_f
21
+ b = row[:b]&.to_f
22
+ d = row[:d]&.to_f
23
+
24
+ infiltration_hash = {
25
+ building_type: building_type,
26
+ climate_zone: climate_zone,
27
+ air_barrier: air_barrier,
28
+ hvac_status: hvac_status,
29
+ a: a,
30
+ b: b,
31
+ d: d
32
+ }
33
+
34
+ # Add the space_type_hash to the result array
35
+ result[:infiltration] << infiltration_hash
36
+ end
37
+
38
+ # Write to the output JSON file
39
+ File.write(output_json, JSON.pretty_generate(result))
40
+
41
+ puts "Data has been converted to JSON and saved to #{output_json}"
42
+ end
43
+
44
+ # convert to json
45
+ infiltration_csv_to_json
46
+
47
+ def infiltration_json_to_csv(input_json = 'NISTInfiltrationCorrelations.json',
48
+ output_csv = 'NISTInfiltrationCorrelations.csv')
49
+ # Read the JSON file
50
+ data = JSON.parse(File.read(input_json), symbolize_names: true)
51
+
52
+ # Prepare the CSV headers
53
+ headers = [
54
+ :building_type,
55
+ :climate_zone,
56
+ :air_barrier,
57
+ :hvac_status,
58
+ :a,
59
+ :b,
60
+ :d
61
+ ]
62
+
63
+ # Write the CSV file
64
+ CSV.open(output_csv, 'w', write_headers: true, headers: headers) do |csv|
65
+ data[:infiltration].each do |infiltration_entry|
66
+ building_type = infiltration_entry[:building_type]
67
+ climate_zone = infiltration_entry[:climate_zone]
68
+ air_barrier = infiltration_entry[:air_barrier]
69
+ hvac_status = infiltration_entry[:hvac_status]
70
+ a = infiltration_entry[:a]
71
+ b = infiltration_entry[:b]
72
+ d = infiltration_entry[:d]
73
+
74
+ csv << [
75
+ building_type,
76
+ climate_zone,
77
+ air_barrier,
78
+ hvac_status,
79
+ a,
80
+ b,
81
+ d
82
+ ]
83
+ end
84
+ end
85
+
86
+ puts "Data has been converted to CSV and saved to #{output_csv}"
87
+ end
@@ -96,7 +96,7 @@ module OpenstudioStandards
96
96
  infil_rate_cfm_per_ft2 = component_infil_rates_cfm_per_ft2[type]['slab_on_grade']
97
97
  end
98
98
  else
99
- OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration', "Could not determine infiltration surface type for #{surface.name}, defaulting to 0 component infiltration rate.")
99
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration.infiltration', "Could not determine infiltration surface type for #{surface.name}, defaulting to 0 component infiltration rate.")
100
100
  return 0.0
101
101
  end
102
102
 
@@ -156,14 +156,14 @@ module OpenstudioStandards
156
156
  when 'OverheadDoor'
157
157
  infil_rate_cfm_per_ft2 = component_infil_rates_cfm_per_ft2[type]['loading_dock_door']
158
158
  when 'GlassDoor'
159
- OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "Assuming swinging_or_revolving_glass_door for #{sub_surface.name} for component infiltration rate.")
159
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration.infiltration', "Assuming swinging_or_revolving_glass_door for #{sub_surface.name} for component infiltration rate.")
160
160
  infil_rate_cfm_per_ft2 = component_infil_rates_cfm_per_ft2[type]['swinging_or_revolving_glass_door']
161
161
  when 'FixedWindow', 'OperableWindow'
162
162
  infil_rate_cfm_per_ft2 = component_infil_rates_cfm_per_ft2[type]['window']
163
163
  when 'Skylight', 'TubularDaylightDome', 'TubularDaylightDiffuser'
164
164
  infil_rate_cfm_per_ft2 = component_infil_rates_cfm_per_ft2[type]['skylight']
165
165
  else
166
- OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration', "Could not determine infiltration sub surface type for #{sub_surface.name}, defaulting to 0 component infiltration rate.")
166
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration.infiltration', "Could not determine infiltration sub surface type for #{sub_surface.name}, defaulting to 0 component infiltration rate.")
167
167
  return 0.0
168
168
  end
169
169
 
@@ -51,11 +51,11 @@ module OpenstudioStandards
51
51
  else
52
52
  nist_building_type = 'RetailStripmall'
53
53
  end
54
- when 'RetailStripmall', 'StripMall', 'Warehouse', 'QuickServiceRestaurant', 'FullServiceRestaurant', 'RtS', 'RSD', 'RFF', 'SCn', 'SUn', 'WRf'
54
+ when 'RetailStripmall', 'StripMall', 'Warehouse', 'QuickServiceRestaurant', 'FullServiceRestaurant', 'RtS', 'RSD', 'RFF', 'SCn', 'SUn', 'WRf', 'Asm', 'MLI'
55
55
  nist_building_type = 'RetailStripmall'
56
- when 'RetailStandalone', 'SuperMarket', 'RtL', 'Gro'
56
+ when 'RetailStandalone', 'SuperMarket', 'RtL', 'Rt3', 'Gro'
57
57
  nist_building_type = 'RetailStandalone'
58
- when 'PrimarySchool', 'EPr'
58
+ when 'PrimarySchool', 'EPr', 'ERC'
59
59
  nist_building_type = 'PrimarySchool'
60
60
  when 'SecondarySchool', 'ESe'
61
61
  nist_building_type = 'SecondarySchool'
@@ -63,26 +63,26 @@ module OpenstudioStandards
63
63
  nist_building_type = 'SmallHotel'
64
64
  when 'LargeHotel', 'Htl'
65
65
  nist_building_type = 'LargeHotel'
66
- when 'Hospital', 'Hsp'
66
+ when 'Hospital', 'Hsp', 'Nrs'
67
67
  nist_building_type = 'Hospital'
68
- when 'MidriseApartment'
68
+ when 'MidriseApartment', 'MFm'
69
69
  nist_building_type = 'MidriseApartment'
70
70
  when 'HighriseApartment'
71
71
  nist_building_type = 'HighriseApartment'
72
72
  when 'TallBuilding', 'SuperTallBuilding'
73
73
  nist_building_type = 'LargeHotel'
74
- OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration', "NIST coefficients aren't available for model building type #{model_building_type}. Since the building type is for a tall building, using nist building type #{nist_building_type} to best represent infiltration coefficients.")
75
- when 'College', 'Laboratory'
74
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration.nist_infiltration', "NIST coefficients aren't available for model building type #{model_building_type}. Since the building type is for a tall building, using nist building type #{nist_building_type} to best represent infiltration coefficients.")
75
+ when 'College', 'Laboratory', 'EUn', 'ECC', 'MBT'
76
76
  nist_building_type = 'SecondarySchool'
77
- OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration', "NIST coefficients aren't available for model building type #{model_building_type}. Since the building may involve complex geometry, using nist building type #{nist_building_type} to best represent infiltration coefficients.")
77
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration.nist_infiltration', "NIST coefficients aren't available for model building type #{model_building_type}. Since the building may involve complex geometry, using nist building type #{nist_building_type} to best represent infiltration coefficients.")
78
78
  when 'Courthouse'
79
79
  nist_building_type = 'MediumOffice'
80
- OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration', "NIST coefficients aren't available for model building type #{model_building_type}. Using nist building type #{nist_building_type} to best represent infiltration coefficients.")
80
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration.nist_infiltration', "NIST coefficients aren't available for model building type #{model_building_type}. Using nist building type #{nist_building_type} to best represent infiltration coefficients.")
81
81
  else
82
82
  nist_building_type = model_building_type
83
83
  end
84
84
 
85
- OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "Using building type #{nist_building_type} for model building type #{model_building_type}.")
85
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration.nist_infiltration', "Using building type #{nist_building_type} for model building type #{model_building_type}.")
86
86
 
87
87
  return nist_building_type
88
88
  end
@@ -112,18 +112,18 @@ module OpenstudioStandards
112
112
  nist_building_type: nil)
113
113
  # validate airtightness value and pressure
114
114
  if airtightness_value < 0.0
115
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration', 'Airtightness value must be postive.')
115
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration.nist_infiltration', 'Airtightness value must be postive.')
116
116
  return false
117
117
  end
118
118
 
119
119
  if airtightness_pressure < 0.0
120
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration', 'Airtightness pressure must be postive.')
120
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration.nist_infiltration', 'Airtightness pressure must be postive.')
121
121
  return false
122
122
  end
123
123
 
124
124
  # calculate infiltration design value at 4 Pa
125
125
  airtightness_value_4pa_per_hr = airtightness_value * ((4.0 / airtightness_pressure)**0.65)
126
- OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "User-inputed airtightness design value #{airtightness_value} (m^3/h-m^2) at #{airtightness_pressure} Pa converts to #{airtightness_value_4pa_per_hr.round(7)} (m^3/h-m^2) at 4 Pa")
126
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration.nist_infiltration', "User-inputed airtightness design value #{airtightness_value} (m^3/h-m^2) at #{airtightness_pressure} Pa converts to #{airtightness_value_4pa_per_hr.round(7)} (m^3/h-m^2) at 4 Pa")
127
127
 
128
128
  # convert to m^3/s-m^2
129
129
  airtightness_value_4pa_per_s = airtightness_value_4pa_per_hr / 3600.0
@@ -150,19 +150,19 @@ module OpenstudioStandards
150
150
  five_sided_area = exterior_wall_area + ground_wall_area + exterior_roof_area + ground_roof_area
151
151
  six_sided_area = exterior_wall_area + ground_wall_area + exterior_roof_area + ground_roof_area + exterior_floor_area + ground_floor_area
152
152
  energy_plus_area = exterior_wall_area + exterior_roof_area
153
- OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "4-sided area = #{four_sided_area.round(2)} m^2, 5-sided area = #{five_sided_area.round(2)} m^2, 6-sided area = #{six_sided_area.round(2)} m^2.")
153
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration.nist_infiltration', "4-sided area = #{four_sided_area.round(2)} m^2, 5-sided area = #{five_sided_area.round(2)} m^2, 6-sided area = #{six_sided_area.round(2)} m^2.")
154
154
 
155
155
  # The SpaceInfiltrationDesignFlowRate object FlowperExteriorSurfaceArea method only counts surfaces with the 'Outdoors' boundary conditions towards exterior surface area, not surfaces with the 'Ground' boundary conditions. That means all values need to be normalized to exterior wall and roof area.
156
156
  case airtightness_area_covered
157
157
  when '4-sided'
158
158
  design_infiltration_4pa = airtightness_value_4pa_per_s * (four_sided_area / energy_plus_area)
159
- OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "#{airtightness_area_covered} infiltration design value #{airtightness_value_4pa_per_s.round(7)} (m^3/s-m^2) converted to #{design_infiltration_4pa.round(7)} (m^3/s-m^2) based on 4-sided area #{four_sided_area.round(2)} m^2 and 5-sided area #{energy_plus_area.round(2)} m^2 excluding ground boundary surfaces for energyplus.")
159
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration.nist_infiltration', "#{airtightness_area_covered} infiltration design value #{airtightness_value_4pa_per_s.round(7)} (m^3/s-m^2) converted to #{design_infiltration_4pa.round(7)} (m^3/s-m^2) based on 4-sided area #{four_sided_area.round(2)} m^2 and 5-sided area #{energy_plus_area.round(2)} m^2 excluding ground boundary surfaces for energyplus.")
160
160
  when '5-sided'
161
161
  design_infiltration_4pa = airtightness_value_4pa_per_s * (five_sided_area / energy_plus_area)
162
- OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "#{airtightness_area_covered} infiltration design value #{airtightness_value_4pa_per_s.round(7)} (m^3/s-m^2) converted to #{design_infiltration_4pa.round(7)} (m^3/s-m^2) based on 5-sided area #{five_sided_area.round(2)} m^2 and 5-sided area #{energy_plus_area.round(2)} m^2 excluding ground boundary surfaces for energyplus.")
162
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration.nist_infiltration', "#{airtightness_area_covered} infiltration design value #{airtightness_value_4pa_per_s.round(7)} (m^3/s-m^2) converted to #{design_infiltration_4pa.round(7)} (m^3/s-m^2) based on 5-sided area #{five_sided_area.round(2)} m^2 and 5-sided area #{energy_plus_area.round(2)} m^2 excluding ground boundary surfaces for energyplus.")
163
163
  when '6-sided'
164
164
  design_infiltration_4pa = airtightness_value_4pa_per_s * (six_sided_area / energy_plus_area)
165
- OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "#{airtightness_area_covered} infiltration design value #{airtightness_value_4pa_per_s.round(7)} (m^3/s-m^2) converted to #{design_infiltration_4pa.round(7)} (m^3/s-m^2) based on 6-sided area #{six_sided_area.round(2)} m^2 and 5-sided area #{energy_plus_area.round(2)} m^2 excluding ground boundary surfaces for energyplus.")
165
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration.nist_infiltration', "#{airtightness_area_covered} infiltration design value #{airtightness_value_4pa_per_s.round(7)} (m^3/s-m^2) converted to #{design_infiltration_4pa.round(7)} (m^3/s-m^2) based on 6-sided area #{six_sided_area.round(2)} m^2 and 5-sided area #{energy_plus_area.round(2)} m^2 excluding ground boundary surfaces for energyplus.")
166
166
  end
167
167
 
168
168
  # validate hvac schedule
@@ -171,7 +171,7 @@ module OpenstudioStandards
171
171
  else
172
172
  hvac_schedule = model.getScheduleByName(hvac_schedule_name)
173
173
  unless hvac_schedule.is_initialized
174
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration', "HVAC schedule argument #{hvac_schedule} not found in the model. It may have been removed by another measure.")
174
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration.nist_infiltration', "HVAC schedule argument #{hvac_schedule} not found in the model. It may have been removed by another measure.")
175
175
  return false
176
176
  end
177
177
  hvac_schedule = hvac_schedule.get
@@ -180,16 +180,16 @@ module OpenstudioStandards
180
180
  elsif hvac_schedule.to_ScheduleConstant.is_initialized
181
181
  hvac_schedule = hvac_schedule.to_ScheduleConstant.get
182
182
  else
183
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration', "HVAC schedule argument #{hvac_schedule} is not a Schedule Constant or Schedule Ruleset object.")
183
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration.nist_infiltration', "HVAC schedule argument #{hvac_schedule} is not a Schedule Constant or Schedule Ruleset object.")
184
184
  return false
185
185
  end
186
186
 
187
- OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "Using HVAC schedule #{hvac_schedule.name} from user arguments to determine infiltration on/off schedule.")
187
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration.nist_infiltration', "Using HVAC schedule #{hvac_schedule.name} from user arguments to determine infiltration on/off schedule.")
188
188
  end
189
189
 
190
190
  # creating infiltration schedules based on hvac schedule
191
191
  if hvac_schedule.nil?
192
- OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration', 'Unable to determine the building HVAC schedule. Treating the building as if there is no HVAC system with outdoor air. This may be appropriate for design sizing, particularly heating design sizing. If this is not the case, input a schedule argument, or assign one to an air loop in the model.')
192
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration.nist_infiltration', 'Unable to determine the building HVAC schedule. Treating the building as if there is no HVAC system with outdoor air. This may be appropriate for design sizing, particularly heating design sizing. If this is not the case, input a schedule argument, or assign one to an air loop in the model.')
193
193
  on_schedule = OpenStudio::Model::ScheduleConstant.new(model)
194
194
  on_schedule.setName('Infiltration HVAC On Schedule')
195
195
  on_schedule.setValue(0.0)
@@ -228,26 +228,26 @@ module OpenstudioStandards
228
228
 
229
229
  # check that model building type is supported
230
230
  unless nist_building_types.include? nist_building_type
231
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration', "NIST coefficients are not available for model building type #{nist_building_type}.")
231
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration.nist_infiltration', "NIST coefficients are not available for model building type #{nist_building_type}.")
232
232
  return false
233
233
  end
234
234
 
235
235
  # remove existing infiltration objects
236
- OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "The modeled started with #{model.getSpaceInfiltrationDesignFlowRates.size} infiltration objects and #{model.getSpaceInfiltrationEffectiveLeakageAreas.size} effective leakage area objects.")
236
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration.nist_infiltration', "The modeled started with #{model.getSpaceInfiltrationDesignFlowRates.size} infiltration objects and #{model.getSpaceInfiltrationEffectiveLeakageAreas.size} effective leakage area objects.")
237
237
  model.getSpaceInfiltrationDesignFlowRates.each(&:remove)
238
238
  model.getSpaceInfiltrationEffectiveLeakageAreas.each(&:remove)
239
239
 
240
240
  # load NIST infiltration correlations file and convert to hash table
241
- nist_infiltration_correlations_csv = "#{__dir__}/data/NISTInfiltrationCorrelations.csv"
242
- unless File.exist?(nist_infiltration_correlations_csv)
243
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration', "Unable to find file: #{nist_infiltration_correlations_csv}")
241
+ nist_infiltration_correlations_json = "#{File.dirname(__FILE__)}/data/NISTInfiltrationCorrelations.json"
242
+ unless File.exist?(nist_infiltration_correlations_json)
243
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration.nist_infiltration', "Unable to find file: #{nist_infiltration_correlations_json}")
244
244
  return false
245
245
  end
246
- coefficients_tbl = CSV.table(nist_infiltration_correlations_csv, encoding: "ISO8859-1:utf-8" )
247
- coefficients_hsh = coefficients_tbl.map(&:to_hash)
246
+ coefficients_hsh = JSON.parse(File.read("#{File.dirname(__FILE__)}/data/NISTInfiltrationCorrelations.json"), symbolize_names: true)
247
+ coefficients_hsh = coefficients_hsh[:infiltration]
248
248
 
249
249
  # select down to building type and climate zone
250
- coefficients = coefficients_hsh.select { |r| (r[:building_type] == nist_building_type) && (r[:climate_zone] == climate_zone_number) }
250
+ coefficients = coefficients_hsh.select { |r| (r[:building_type] == nist_building_type) && (r[:climate_zone].to_i == climate_zone_number) }
251
251
 
252
252
  # filter by air barrier
253
253
  if air_barrier
@@ -258,14 +258,14 @@ module OpenstudioStandards
258
258
 
259
259
  # determine coefficients
260
260
  # if no off coefficients are defined, use 0 for a and the on coefficients for b and d
261
- on_coefficients = coefficients.select { |r| r[:hvac_status] == 'on' }
262
- off_coefficients = coefficients.select { |r| r[:hvac_status] == 'off' }
263
- a_on = on_coefficients[0][:a]
264
- b_on = on_coefficients[0][:b]
265
- d_on = on_coefficients[0][:d]
266
- a_off = off_coefficients[0][:a].nil? ? on_coefficients[0][:a] : off_coefficients[0][:a]
267
- b_off = off_coefficients[0][:b].nil? ? on_coefficients[0][:b] : off_coefficients[0][:b]
268
- d_off = off_coefficients[0][:d].nil? ? on_coefficients[0][:d] : off_coefficients[0][:d]
261
+ on_coefficients = coefficients.select { |r| r[:hvac_status] == 'on' }[0]
262
+ off_coefficients = coefficients.select { |r| r[:hvac_status] == 'off' }[0]
263
+ a_on = on_coefficients[:a]
264
+ b_on = on_coefficients[:b]
265
+ d_on = on_coefficients[:d]
266
+ a_off = off_coefficients[:a].nil? ? on_coefficients[:a] : off_coefficients[:a]
267
+ b_off = off_coefficients[:b].nil? ? on_coefficients[:b] : off_coefficients[:b]
268
+ d_off = off_coefficients[:d].nil? ? on_coefficients[:d] : off_coefficients[:d]
269
269
 
270
270
  # add new infiltration objects
271
271
  # define infiltration as flow per exterior area
@@ -293,7 +293,7 @@ module OpenstudioStandards
293
293
  hvac_off_infiltration.setSchedule(off_schedule)
294
294
  end
295
295
 
296
- OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "The modeled finished with #{model.getSpaceInfiltrationDesignFlowRates.size} infiltration objects.")
296
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration.nist_infiltration', "The modeled finished with #{model.getSpaceInfiltrationDesignFlowRates.size} infiltration objects.")
297
297
 
298
298
  return true
299
299
  end
@@ -315,7 +315,7 @@ module OpenstudioStandards
315
315
  hvac_schedule = OpenstudioStandards::Schedules.model_get_hvac_schedule(model)
316
316
  else
317
317
  unless hvac_schedule.to_Schedule.is_initialized
318
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration', "HVAC schedule argument #{hvac_schedule} not found in the model or is not a Schedule object. It may have been removed by another measure.")
318
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration.nist_infiltration', "HVAC schedule argument #{hvac_schedule} not found in the model or is not a Schedule object. It may have been removed by another measure.")
319
319
  return false
320
320
  end
321
321
  hvac_schedule = hvac_schedule.to_Schedule.get
@@ -324,16 +324,16 @@ module OpenstudioStandards
324
324
  elsif hvac_schedule.to_ScheduleConstant.is_initialized
325
325
  hvac_schedule = hvac_schedule.to_ScheduleConstant.get
326
326
  else
327
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration', "HVAC schedule argument #{hvac_schedule} is not a Schedule Constant or Schedule Ruleset object.")
327
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Infiltration.nist_infiltration', "HVAC schedule argument #{hvac_schedule} is not a Schedule Constant or Schedule Ruleset object.")
328
328
  return false
329
329
  end
330
330
 
331
- OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration', "Using HVAC schedule #{hvac_schedule.name} from user arguments to determine infiltration on/off schedule.")
331
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Infiltration.nist_infiltration', "Using HVAC schedule #{hvac_schedule.name} from user arguments to determine infiltration on/off schedule.")
332
332
  end
333
333
 
334
334
  # creating infiltration schedules based on hvac schedule
335
335
  if hvac_schedule.nil?
336
- OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration', 'Unable to determine the HVAC schedule. Treating the building as if there is no HVAC system with outdoor air. If this is not the case, input a schedule argument, or assign one to an air loop in the model.')
336
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Infiltration.nist_infiltration', 'Unable to determine the HVAC schedule. Treating the building as if there is no HVAC system with outdoor air. If this is not the case, input a schedule argument, or assign one to an air loop in the model.')
337
337
  on_schedule = OpenStudio::Model::ScheduleConstant.new(model)
338
338
  on_schedule.setName('Infiltration HVAC On Schedule')
339
339
  on_schedule.setValue(0.0)
@@ -96,8 +96,8 @@ module OpenstudioStandards
96
96
 
97
97
  # Dripdown schedule
98
98
  dripdown_sch = OpenStudio::Model::ScheduleRuleset.new(model)
99
- dripdown_sch.setName("#{ref_case.name} Defrost")
100
- dripdown_sch.defaultDaySchedule.setName("#{ref_case.name} Defrost Default")
99
+ dripdown_sch.setName("#{ref_case.name} Dripdown")
100
+ dripdown_sch.defaultDaySchedule.setName("#{ref_case.name} Dripdown Default")
101
101
  dripdown_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, i, 0, 0), 0)
102
102
  dripdown_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, i, 59, 0), 1)
103
103
  dripdown_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 0)
@@ -8,11 +8,11 @@ module OpenstudioStandards
8
8
  #
9
9
  # @param model [OpenStudio::Model::Model] OpenStudio model object
10
10
  # @param template [String] Technology or standards level, either 'old', 'new', or 'advanced'
11
- # @param separate_system_size_limit [Float] The area in square feet above which a refrigeration system will be split into multiple systems
11
+ # @param separate_system_size_limit [Float] The area in square feet above which a refrigeration system will be split into multiple systems. Currently not used.
12
12
  # @return [Boolean] returns true if successful, false if not
13
13
  def self.create_typical_refrigeration(model,
14
14
  template: 'new',
15
- separate_system_size_limit: 20000.0)
15
+ separate_system_size_limit: 0.0)
16
16
  # get refrigeration equipment list based on space types and area
17
17
  ref_equip_list = OpenstudioStandards::Refrigeration.typical_refrigeration_equipment_list(model)
18
18
 
@@ -71,25 +71,26 @@ module OpenstudioStandards
71
71
  end
72
72
  end
73
73
 
74
- refrigeration_space_type_area = OpenStudio.convert(model.getBuilding.floorArea, 'm^2', 'ft^2').get
75
- if refrigeration_space_type_area < separate_system_size_limit
76
- # each case is self-contained
77
- medium_temperature_cases.each { |ref_equip| OpenstudioStandards::Refrigeration.create_compressor_rack(model, ref_equip, template: template) }
78
- low_temperature_cases.each { |ref_equip| OpenstudioStandards::Refrigeration.create_compressor_rack(model, ref_equip, template: template) }
79
-
80
- # each walkin gets its own refrigeration system
81
- medium_temperature_walkins.each { |ref_equip| OpenstudioStandards::Refrigeration.create_refrigeration_system(model, [ref_equip], template: template, operation_type: 'MT') }
82
- low_temperature_walkins.each { |ref_equip| OpenstudioStandards::Refrigeration.create_refrigeration_system(model, [ref_equip], template: template, operation_type: 'LT') }
83
- else
84
- medium_temperature_equip = medium_temperature_cases + medium_temperature_walkins
85
- OpenstudioStandards::Refrigeration.create_refrigeration_system(model, medium_temperature_equip,
86
- template: template,
87
- operation_type: 'MT')
88
- low_temperature_equip = low_temperature_cases + low_temperature_walkins
89
- OpenstudioStandards::Refrigeration.create_refrigeration_system(model, low_temperature_equip,
90
- template: template,
91
- operation_type: 'LT')
92
- end
74
+ # @todo Disable self-contained refrigeration units until we have efficiency data and cases and walkins can connect to those systems and simulate correctly.
75
+ # refrigeration_space_type_area = OpenStudio.convert(model.getBuilding.floorArea, 'm^2', 'ft^2').get
76
+ # if refrigeration_space_type_area < separate_system_size_limit
77
+ # # each case is self-contained
78
+ # medium_temperature_cases.each { |ref_equip| OpenstudioStandards::Refrigeration.create_compressor_rack(model, ref_equip, template: template) }
79
+ # low_temperature_cases.each { |ref_equip| OpenstudioStandards::Refrigeration.create_compressor_rack(model, ref_equip, template: template) }
80
+
81
+ # # each walkin gets its own refrigeration system
82
+ # medium_temperature_walkins.each { |ref_equip| OpenstudioStandards::Refrigeration.create_refrigeration_system(model, [ref_equip], template: template, operation_type: 'MT') }
83
+ # low_temperature_walkins.each { |ref_equip| OpenstudioStandards::Refrigeration.create_refrigeration_system(model, [ref_equip], template: template, operation_type: 'LT') }
84
+ # else
85
+ medium_temperature_equip = medium_temperature_cases + medium_temperature_walkins
86
+ OpenstudioStandards::Refrigeration.create_refrigeration_system(model, medium_temperature_equip,
87
+ template: template,
88
+ operation_type: 'MT')
89
+ low_temperature_equip = low_temperature_cases + low_temperature_walkins
90
+ OpenstudioStandards::Refrigeration.create_refrigeration_system(model, low_temperature_equip,
91
+ template: template,
92
+ operation_type: 'LT')
93
+ # end
93
94
 
94
95
  return true
95
96
  end
@@ -41,7 +41,7 @@ module OpenstudioStandards
41
41
  standards_building_type = space_type.standardsBuildingType.get
42
42
 
43
43
  # load typical water use equipment data
44
- data = JSON.parse(File.read("#{__dir__}/data/typical_water_use_equipment.json"), symbolize_names: true)
44
+ data = JSON.parse(File.read("#{File.dirname(__FILE__)}/data/typical_water_use_equipment.json"), symbolize_names: true)
45
45
  space_type_properties = data[:space_types].select { |hash| (hash[:space_type] == standards_space_type) && (hash[:building_type] == standards_building_type) }
46
46
 
47
47
  # skip spaces with no equipment defined
@@ -1254,6 +1254,9 @@ class Standard
1254
1254
 
1255
1255
  # Get climate zone
1256
1256
  climate_zone = OpenstudioStandards::Weather.model_get_climate_zone(space.model)
1257
+ if climate_zone.empty?
1258
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Space', 'Model has no climate zone assigned, cannot determine space conditioning category.')
1259
+ end
1257
1260
 
1258
1261
  # Get the zone this space is inside
1259
1262
  zone = space.thermalZone
@@ -29,7 +29,7 @@ class ASHRAE9012013 < ASHRAE901
29
29
  # Moisture regime is not needed for climate zone 8
30
30
  climate_zone = climate_zone.split('-')[-1]
31
31
  climate_zone = '8' if climate_zone.include?('8')
32
-
32
+
33
33
  search_criteria = {
34
34
  'template' => template,
35
35
  'climate_zone' => climate_zone
@@ -455,6 +455,13 @@ class ASHRAE9012013 < ASHRAE901
455
455
  # Moisture regime is not needed for climate zone 8
456
456
  climate_zone = climate_zone.split('-')[-1]
457
457
  climate_zone = '8' if climate_zone.include?('8')
458
+ # Default to use values for cooling for climate zones 0, 1, 2, and 3 and heating for all others.
459
+ case climate_zone
460
+ when '0A', '0B', '1A', '1A', '1B', '2A', '2B', '3A', '3B', '3C'
461
+ design_conditions = 'Cooling'
462
+ else
463
+ design_conditions = 'Heating'
464
+ end
458
465
 
459
466
  # Check annual operating hours
460
467
  if ann_op_hrs < 8000.0
@@ -469,7 +476,8 @@ class ASHRAE9012013 < ASHRAE901
469
476
  search_criteria = {
470
477
  'template' => template,
471
478
  'climate_zone' => climate_zone,
472
- 'under_8000_hours' => under_8000_hours
479
+ 'under_8000_hours' => under_8000_hours,
480
+ 'design_conditions' => design_conditions
473
481
  }
474
482
  energy_recovery_limits = model_find_object(standards_data['energy_recovery'], search_criteria)
475
483
  if energy_recovery_limits.nil?