openstudio-extension 0.7.1 → 0.8.0

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +14 -0
  4. data/LICENSE.md +1 -1
  5. data/README.md +2 -0
  6. data/lib/openstudio/extension/runner.rb +12 -8
  7. data/lib/openstudio/extension/runner_config.rb +33 -6
  8. data/lib/openstudio/extension/version.rb +1 -1
  9. data/openstudio-extension.gemspec +6 -6
  10. metadata +15 -66
  11. data/lib/openstudio/extension/core/CreateResults.rb +0 -1033
  12. data/lib/openstudio/extension/core/check_air_sys_temps.rb +0 -160
  13. data/lib/openstudio/extension/core/check_calibration.rb +0 -125
  14. data/lib/openstudio/extension/core/check_cond_zns.rb +0 -54
  15. data/lib/openstudio/extension/core/check_domestic_hot_water.rb +0 -304
  16. data/lib/openstudio/extension/core/check_envelope_conductance.rb +0 -423
  17. data/lib/openstudio/extension/core/check_eui_by_end_use.rb +0 -132
  18. data/lib/openstudio/extension/core/check_eui_reasonableness.rb +0 -105
  19. data/lib/openstudio/extension/core/check_fan_pwr.rb +0 -68
  20. data/lib/openstudio/extension/core/check_internal_loads.rb +0 -363
  21. data/lib/openstudio/extension/core/check_mech_sys_capacity.rb +0 -196
  22. data/lib/openstudio/extension/core/check_mech_sys_efficiency.rb +0 -296
  23. data/lib/openstudio/extension/core/check_mech_sys_part_load_eff.rb +0 -434
  24. data/lib/openstudio/extension/core/check_mech_sys_type.rb +0 -109
  25. data/lib/openstudio/extension/core/check_part_loads.rb +0 -421
  26. data/lib/openstudio/extension/core/check_placeholder.rb +0 -45
  27. data/lib/openstudio/extension/core/check_plant_cap.rb +0 -93
  28. data/lib/openstudio/extension/core/check_plant_temps.rb +0 -129
  29. data/lib/openstudio/extension/core/check_plenum_loads.rb +0 -57
  30. data/lib/openstudio/extension/core/check_pump_pwr.rb +0 -78
  31. data/lib/openstudio/extension/core/check_sch_coord.rb +0 -211
  32. data/lib/openstudio/extension/core/check_schedules.rb +0 -281
  33. data/lib/openstudio/extension/core/check_simultaneous_heating_and_cooling.rb +0 -128
  34. data/lib/openstudio/extension/core/check_supply_air_and_thermostat_temp_difference.rb +0 -118
  35. data/lib/openstudio/extension/core/check_weather_files.rb +0 -102
  36. data/lib/openstudio/extension/core/deer_vintages.rb +0 -281
  37. data/lib/openstudio/extension/core/os_lib_aedg_measures.rb +0 -461
  38. data/lib/openstudio/extension/core/os_lib_constructions.rb +0 -353
  39. data/lib/openstudio/extension/core/os_lib_geometry.rb +0 -1169
  40. data/lib/openstudio/extension/core/os_lib_helper_methods.rb +0 -383
  41. data/lib/openstudio/extension/core/os_lib_hvac.rb +0 -2163
  42. data/lib/openstudio/extension/core/os_lib_lighting_and_equipment.rb +0 -184
  43. data/lib/openstudio/extension/core/os_lib_model_generation.rb +0 -3584
  44. data/lib/openstudio/extension/core/os_lib_model_simplification.rb +0 -1019
  45. data/lib/openstudio/extension/core/os_lib_outdoorair_and_infiltration.rb +0 -135
  46. data/lib/openstudio/extension/core/os_lib_reporting_qaqc.rb +0 -170
  47. data/lib/openstudio/extension/core/os_lib_schedules.rb +0 -933
@@ -1,129 +0,0 @@
1
- # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
3
- # See also https://openstudio.net/license
4
- # *******************************************************************************
5
-
6
- module OsLib_QAQC
7
- # Check the plant loop operational vs. sizing temperatures
8
- # and make sure everything is coordinated. This identifies problems
9
- # caused by sizing to one set of conditions and operating at a different set.
10
- def check_plant_temps(category, target_standard, max_sizing_temp_delta = 0.1, name_only = false)
11
- # summary of the check
12
- check_elems = OpenStudio::AttributeVector.new
13
- check_elems << OpenStudio::Attribute.new('name', 'Plant Loop Temperatures')
14
- check_elems << OpenStudio::Attribute.new('category', category)
15
- check_elems << OpenStudio::Attribute.new('description', 'Check that plant loop sizing and operation temperatures are coordinated.')
16
-
17
- # stop here if only name is requested this is used to populate display name for arguments
18
- if name_only == true
19
- results = []
20
- check_elems.each do |elem|
21
- results << elem.valueAsString
22
- end
23
- return results
24
- end
25
-
26
- std = Standard.build(target_standard)
27
-
28
- begin
29
- # Check each plant loop in the model
30
- @model.getPlantLoops.sort.each do |plant_loop|
31
- loop_name = plant_loop.name.to_s
32
-
33
- # Get the central heating and cooling SAT for sizing
34
- sizing_plant = plant_loop.sizingPlant
35
- loop_siz_f = OpenStudio.convert(sizing_plant.designLoopExitTemperature, 'C', 'F').get
36
-
37
- # Determine the min and max operational temperatures
38
- loop_op_min_f = nil
39
- loop_op_max_f = nil
40
- plant_loop.supplyOutletNode.setpointManagers.each do |spm|
41
- obj_type = spm.iddObjectType.valueName.to_s
42
- case obj_type
43
- when 'OS_SetpointManager_Scheduled'
44
- sch = spm.to_SetpointManagerScheduled.get.schedule
45
- if sch.to_ScheduleRuleset.is_initialized
46
- min_c = std.schedule_ruleset_annual_min_max_value(sch.to_ScheduleRuleset.get)['min']
47
- max_c = std.schedule_ruleset_annual_min_max_value(sch.to_ScheduleRuleset.get)['max']
48
- elsif sch.to_ScheduleConstant.is_initialized
49
- min_c = std.schedule_constant_annual_min_max_value(sch.to_ScheduleConstant.get)['min']
50
- max_c = std.schedule_constant_annual_min_max_value(sch.to_ScheduleConstant.get)['max']
51
- else
52
- next
53
- end
54
- loop_op_min_f = OpenStudio.convert(min_c, 'C', 'F').get
55
- loop_op_max_f = OpenStudio.convert(max_c, 'C', 'F').get
56
- when 'OS_SetpointManager_Scheduled_DualSetpoint'
57
- spm = spm.to_SetpointManagerSingleZoneReheat.get
58
- # Lowest setpoint is minimum of low schedule
59
- low_sch = spm.to_SetpointManagerScheduled.get.lowSetpointSchedule
60
- next if low_sch.empty?
61
- low_sch = low_sch.get
62
- if low_sch.to_ScheduleRuleset.is_initialized
63
- min_c = std.schedule_ruleset_annual_min_max_value(low_sch.to_ScheduleRuleset.get)['min']
64
- max_c = std.schedule_ruleset_annual_min_max_value(low_sch.to_ScheduleRuleset.get)['max']
65
- elsif low_sch.to_ScheduleConstant.is_initialized
66
- min_c = std.schedule_constant_annual_min_max_value(low_sch.to_ScheduleConstant.get)['min']
67
- max_c = std.schedule_constant_annual_min_max_value(low_sch.to_ScheduleConstant.get)['max']
68
- else
69
- next
70
- end
71
- loop_op_min_f = OpenStudio.convert(min_c, 'C', 'F').get
72
- # Highest setpoint it maximum of high schedule
73
- high_sch = spm.to_SetpointManagerScheduled.get.highSetpointSchedule
74
- next if high_sch.empty?
75
- high_sch = high_sch.get
76
- if high_sch.to_ScheduleRuleset.is_initialized
77
- min_c = std.schedule_ruleset_annual_min_max_value(high_sch.to_ScheduleRuleset.get)['min']
78
- max_c = std.schedule_ruleset_annual_min_max_value(high_sch.to_ScheduleRuleset.get)['max']
79
- elsif high_sch.to_ScheduleConstant.is_initialized
80
- min_c = std.schedule_constant_annual_min_max_value(high_sch.to_ScheduleConstant.get)['min']
81
- max_c = std.schedule_constant_annual_min_max_value(high_sch.to_ScheduleConstant.get)['max']
82
- else
83
- next
84
- end
85
- loop_op_max_f = OpenStudio.convert(max_c, 'C', 'F').get
86
- when 'OS_SetpointManager_OutdoorAirReset'
87
- spm = spm.to_SetpointManagerOutdoorAirReset.get
88
- temp_1_f = OpenStudio.convert(spm.setpointatOutdoorHighTemperature, 'C', 'F').get
89
- temp_2_f = OpenStudio.convert(spm.setpointatOutdoorLowTemperature, 'C', 'F').get
90
- loop_op_min_f = [temp_1_f, temp_2_f].min
91
- loop_op_max_f = [temp_1_f, temp_2_f].max
92
- else
93
- next # Only check the commonly used setpoint managers
94
- end
95
- end
96
-
97
- # Compare plant loop sizing temperatures to operational temperatures
98
- case sizing_plant.loopType
99
- when 'Heating'
100
- if loop_op_max_f
101
- if ((loop_op_max_f - loop_siz_f) / loop_op_max_f).abs > max_sizing_temp_delta
102
- check_elems << OpenStudio::Attribute.new('flag', "For #{plant_loop.name}, the sizing is done with a supply water temp of #{loop_siz_f.round(2)}F, but the setpoint manager controlling the loop operates up to #{loop_op_max_f.round(2)}F. These are farther apart than the acceptable #{(max_sizing_temp_delta * 100.0).round(2)}% difference.")
103
- end
104
- end
105
- when 'Cooling'
106
- if loop_op_min_f
107
- if ((loop_op_min_f - loop_siz_f) / loop_op_min_f).abs > max_sizing_temp_delta
108
- check_elems << OpenStudio::Attribute.new('flag', "For #{plant_loop.name}, the sizing is done with a supply water temp of #{loop_siz_f.round(2)}F, but the setpoint manager controlling the loop operates down to #{loop_op_min_f.round(2)}F. These are farther apart than the acceptable #{(max_sizing_temp_delta * 100.0).round(2)}% difference.")
109
- end
110
- end
111
- when 'Condenser'
112
- # Not checking sizing of condenser loops
113
- end
114
- end
115
- rescue StandardError => e
116
- # brief description of ruby error
117
- check_elems << OpenStudio::Attribute.new('flag', "Error prevented QAQC check from running (#{e}).")
118
-
119
- # backtrace of ruby error for diagnostic use
120
- if @error_backtrace then check_elems << OpenStudio::Attribute.new('flag', e.backtrace.join("\n").to_s) end
121
- end
122
-
123
- # add check_elms to new attribute
124
- check_elem = OpenStudio::Attribute.new('check', check_elems)
125
-
126
- return check_elem
127
- # note: registerWarning and registerValue will be added for checks downstream using os_lib_reporting_qaqc.rb
128
- end
129
- end
@@ -1,57 +0,0 @@
1
- # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
3
- # See also https://openstudio.net/license
4
- # *******************************************************************************
5
-
6
- module OsLib_QAQC
7
- # Check that there are no people or lights in plenums.
8
- def check_plenum_loads(category, target_standard, name_only = false)
9
- # summary of the check
10
- check_elems = OpenStudio::AttributeVector.new
11
- check_elems << OpenStudio::Attribute.new('name', 'Plenum Loads')
12
- check_elems << OpenStudio::Attribute.new('category', category)
13
- check_elems << OpenStudio::Attribute.new('description', 'Check that the plenums do not have people or lights.')
14
-
15
- # stop here if only name is requested this is used to populate display name for arguments
16
- if name_only == true
17
- results = []
18
- check_elems.each do |elem|
19
- results << elem.valueAsString
20
- end
21
- return results
22
- end
23
-
24
- std = Standard.build(target_standard)
25
-
26
- begin
27
- @model.getThermalZones.each do |zone|
28
- # Only check plenums
29
- next unless std.thermal_zone_plenum?(zone)
30
-
31
- # People
32
- num_people = zone.numberOfPeople
33
- if num_people > 0
34
- check_elems << OpenStudio::Attribute.new('flag', "#{zone.name} is a plenum, but has #{num_people.round(1)} people. Plenums should not contain people.")
35
- end
36
-
37
- # Lights
38
- lights_w = zone.lightingPower
39
- if lights_w > 0
40
- check_elems << OpenStudio::Attribute.new('flag', "#{zone.name} is a plenum, but has #{lights_w.round(1)} W of lights. Plenums should not contain lights.")
41
- end
42
- end
43
- rescue StandardError => e
44
- # brief description of ruby error
45
- check_elems << OpenStudio::Attribute.new('flag', "Error prevented QAQC check from running (#{e}).")
46
-
47
- # backtrace of ruby error for diagnostic use
48
- if @error_backtrace then check_elems << OpenStudio::Attribute.new('flag', e.backtrace.join("\n").to_s) end
49
- end
50
-
51
- # add check_elms to new attribute
52
- check_elem = OpenStudio::Attribute.new('check', check_elems)
53
-
54
- return check_elem
55
- # note: registerWarning and registerValue will be added for checks downstream using os_lib_reporting_qaqc.rb
56
- end
57
- end
@@ -1,78 +0,0 @@
1
- # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
3
- # See also https://openstudio.net/license
4
- # *******************************************************************************
5
-
6
- module OsLib_QAQC
7
- # Check the pumping power (W/gpm) for each pump in the model to identify
8
- # unrealistically sized pumps.
9
- def check_pump_pwr(category, target_standard, max_pwr_delta = 0.1, name_only = false)
10
- # summary of the check
11
- check_elems = OpenStudio::AttributeVector.new
12
- check_elems << OpenStudio::Attribute.new('name', 'Pump Power')
13
- check_elems << OpenStudio::Attribute.new('category', category)
14
- check_elems << OpenStudio::Attribute.new('description', 'Check that pump power vs flow makes sense.')
15
-
16
- # stop here if only name is requested this is used to populate display name for arguments
17
- if name_only == true
18
- results = []
19
- check_elems.each do |elem|
20
- results << elem.valueAsString
21
- end
22
- return results
23
- end
24
-
25
- std = Standard.build(target_standard)
26
-
27
- begin
28
- # Check each plant loop
29
- @model.getPlantLoops.each do |plant_loop|
30
- # Set the expected/typical W/gpm
31
- loop_type = plant_loop.sizingPlant.loopType
32
- case loop_type
33
- when 'Heating'
34
- expected_w_per_gpm = 19.0
35
- when 'Cooling'
36
- expected_w_per_gpm = 22.0
37
- when 'Condenser'
38
- expected_w_per_gpm = 19.0
39
- end
40
-
41
- # Check the W/gpm for each pump on each plant loop
42
- plant_loop.supplyComponents.each do |sc|
43
- # Get the W/gpm for the pump
44
- obj_type = sc.iddObjectType.valueName.to_s
45
- case obj_type
46
- when 'OS_Pump_ConstantSpeed'
47
- actual_w_per_gpm = std.pump_rated_w_per_gpm(sc.to_PumpConstantSpeed.get)
48
- when 'OS_Pump_VariableSpeed'
49
- actual_w_per_gpm = std.pump_rated_w_per_gpm(sc.to_PumpVariableSpeed.get)
50
- when 'OS_HeaderedPumps_ConstantSpeed'
51
- actual_w_per_gpm = std.pump_rated_w_per_gpm(sc.to_HeaderedPumpsConstantSpeed.get)
52
- when 'OS_HeaderedPumps_VariableSpeed'
53
- actual_w_per_gpm = std.pump_rated_w_per_gpm(sc.to_HeaderedPumpsVariableSpeed.get)
54
- else
55
- next # Skip non-pump objects
56
- end
57
-
58
- # Compare W/gpm to expected/typical values
59
- if ((expected_w_per_gpm - actual_w_per_gpm) / actual_w_per_gpm).abs > max_pwr_delta
60
- check_elems << OpenStudio::Attribute.new('flag', "For #{sc.name} on #{plant_loop.name}, the actual pumping power of #{actual_w_per_gpm.round(1)} W/gpm is more than #{(max_pwr_delta * 100.0).round(2)}% different from the expected #{expected_w_per_gpm} W/gpm for a #{loop_type} plant loop.")
61
- end
62
- end
63
- end
64
- rescue StandardError => e
65
- # brief description of ruby error
66
- check_elems << OpenStudio::Attribute.new('flag', "Error prevented QAQC check from running (#{e}).")
67
-
68
- # backtrace of ruby error for diagnostic use
69
- if @error_backtrace then check_elems << OpenStudio::Attribute.new('flag', e.backtrace.join("\n").to_s) end
70
- end
71
-
72
- # add check_elms to new attribute
73
- check_elem = OpenStudio::Attribute.new('check', check_elems)
74
-
75
- return check_elem
76
- # note: registerWarning and registerValue will be added for checks downstream using os_lib_reporting_qaqc.rb
77
- end
78
- end
@@ -1,211 +0,0 @@
1
- # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
3
- # See also https://openstudio.net/license
4
- # *******************************************************************************
5
-
6
- module OsLib_QAQC
7
- # Determine the hour when the schedule first exceeds the starting value and when
8
- # it goes back down to the ending value at the end of the day.
9
- # This method only works for ScheduleRuleset schedules.
10
- def get_start_and_end_times(schedule_ruleset)
11
- # Ensure that this is a ScheduleRuleset
12
- schedule_ruleset = schedule_ruleset.to_ScheduleRuleset
13
- return [nil, nil] if schedule_ruleset.empty?
14
- schedule_ruleset = schedule_ruleset.get
15
-
16
- # Define the start and end date
17
- year_start_date = nil
18
- year_end_date = nil
19
- if schedule_ruleset.model.yearDescription.is_initialized
20
- year_description = schedule_ruleset.model.yearDescription.get
21
- year = year_description.assumedYear
22
- year_start_date = OpenStudio::Date.new(OpenStudio::MonthOfYear.new('January'), 1, year)
23
- year_end_date = OpenStudio::Date.new(OpenStudio::MonthOfYear.new('December'), 31, year)
24
- else
25
- year_start_date = OpenStudio::Date.new(OpenStudio::MonthOfYear.new('January'), 1, 2009)
26
- year_end_date = OpenStudio::Date.new(OpenStudio::MonthOfYear.new('December'), 31, 2009)
27
- end
28
-
29
- # Get the ordered list of all the day schedules that are used by this schedule ruleset
30
- day_schs = schedule_ruleset.getDaySchedules(year_start_date, year_end_date)
31
-
32
- # Get a 365-value array of which schedule is used on each day of the year,
33
- day_schs_used_each_day = schedule_ruleset.getActiveRuleIndices(year_start_date, year_end_date)
34
-
35
- # Create a map that shows how many days each schedule is used
36
- day_sch_freq = day_schs_used_each_day.group_by { |n| n }
37
- day_sch_freq = day_sch_freq.sort_by { |freq| freq[1].size }
38
- common_day_freq = day_sch_freq.last
39
-
40
- # Build a hash that maps schedule day index to schedule day
41
- schedule_index_to_day = {}
42
- day_schs.each_with_index do |day_sch, i|
43
- schedule_index_to_day[day_schs_used_each_day[i]] = day_sch
44
- end
45
-
46
- # Get the most common day schedule
47
- sch_index = common_day_freq[0]
48
- number_of_days_sch_used = common_day_freq[1].size
49
-
50
- # Get the day schedule at this index
51
- day_sch = if sch_index == -1 # If index = -1, this day uses the default day schedule (not a rule)
52
- schedule_ruleset.defaultDaySchedule
53
- else
54
- schedule_index_to_day[sch_index]
55
- end
56
-
57
- # Determine the full load hours for just one day
58
- values = []
59
- times = []
60
- day_sch.times.each_with_index do |time, i|
61
- times << day_sch.times[i]
62
- values << day_sch.values[i]
63
- end
64
-
65
- # Get the minimum value
66
- start_val = values.first
67
- end_val = values.last
68
-
69
- # Get the start time (first time value goes above minimum)
70
- start_time = nil
71
- values.each_with_index do |val, i|
72
- break if i == values.size - 1 # Stop if we reach end of array
73
- if val == start_val && values[i + 1] > start_val
74
- start_time = times[i + 1]
75
- break
76
- end
77
- end
78
-
79
- # Get the end time (first time value goes back down to minimum)
80
- end_time = nil
81
- values.each_with_index do |val, i|
82
- if i < values.size - 1
83
- if val > end_val && values[i + 1] == end_val
84
- end_time = times[i]
85
- break
86
- end
87
- else
88
- if val > end_val && values[0] == start_val # Check first hour of day for schedules that end at midnight
89
- end_time = OpenStudio::Time.new(0, 24, 0, 0)
90
- break
91
- end
92
- end
93
- end
94
-
95
- return [start_time, end_time]
96
- end
97
-
98
- # Check that the lighting, equipment, and HVAC setpoint schedules
99
- # coordinate with the occupancy schedules. This is defined as having start and end
100
- # times within the specified number of hours away from the occupancy schedule.
101
- def check_sch_coord(category, target_standard, max_hrs, name_only = false)
102
- # summary of the check
103
- check_elems = OpenStudio::AttributeVector.new
104
- check_elems << OpenStudio::Attribute.new('name', 'Conditioned Zones')
105
- check_elems << OpenStudio::Attribute.new('category', category)
106
- check_elems << OpenStudio::Attribute.new('description', 'Check that lighting, equipment, and HVAC schedules coordinate with occupancy.')
107
-
108
- # stop here if only name is requested this is used to populate display name for arguments
109
- if name_only == true
110
- results = []
111
- check_elems.each do |elem|
112
- results << elem.valueAsString
113
- end
114
- return results
115
- end
116
-
117
- std = Standard.build(target_standard)
118
-
119
- begin
120
- # Convert max hr limit to OpenStudio Time
121
- max_hrs = OpenStudio::Time.new(0, max_hrs, 0, 0)
122
-
123
- # Check schedules in each space
124
- @model.getSpaces.each do |space|
125
- # Occupancy, Lighting, and Equipment Schedules
126
- coord_schs = []
127
- occ_schs = []
128
- # Get the space type (optional)
129
- space_type = space.spaceType
130
-
131
- # Occupancy
132
- occs = []
133
- occs += space.people # From space directly
134
- occs += space_type.get.people if space_type.is_initialized # Inherited from space type
135
- occs.each do |occ|
136
- occ_schs << occ.numberofPeopleSchedule.get if occ.numberofPeopleSchedule.is_initialized
137
- end
138
-
139
- # Lights
140
- lts = []
141
- lts += space.lights # From space directly
142
- lts += space_type.get.lights if space_type.is_initialized # Inherited from space type
143
- lts.each do |lt|
144
- coord_schs << lt.schedule.get if lt.schedule.is_initialized
145
- end
146
-
147
- # Equip
148
- plugs = []
149
- plugs += space.electricEquipment # From space directly
150
- plugs += space_type.get.electricEquipment if space_type.is_initialized # Inherited from space type
151
- plugs.each do |plug|
152
- coord_schs << plug.schedule.get if plug.schedule.is_initialized
153
- end
154
-
155
- # HVAC Schedule (airloop-served zones only)
156
- if space.thermalZone.is_initialized
157
- zone = space.thermalZone.get
158
- if zone.airLoopHVAC.is_initialized
159
- coord_schs << zone.airLoopHVAC.get.availabilitySchedule
160
- end
161
- end
162
-
163
- # Cannot check spaces with no occupancy schedule to compare against
164
- next if occ_schs.empty?
165
-
166
- # Get start and end occupancy times from the first occupancy schedule
167
- occ_start_time, occ_end_time = get_start_and_end_times(occ_schs[0])
168
-
169
- # Cannot check a space where the occupancy start time or end time cannot be determined
170
- next if occ_start_time.nil? || occ_end_time.nil?
171
-
172
- # Check all schedules against occupancy
173
-
174
- # Lights should have a start and end within X hrs of the occupancy start and end
175
- coord_schs.each do |coord_sch|
176
- # Get start and end time of load/HVAC schedule
177
- start_time, end_time = get_start_and_end_times(coord_sch)
178
- if start_time.nil?
179
- check_elems << OpenStudio::Attribute.new('flag', "Could not determine start time of a schedule called #{coord_sch.name}, cannot determine if schedule coordinates with occupancy schedule.")
180
- next
181
- elsif end_time.nil?
182
- check_elems << OpenStudio::Attribute.new('flag', "Could not determine end time of a schedule called #{coord_sch.name}, cannot determine if schedule coordinates with occupancy schedule.")
183
- next
184
- end
185
-
186
- # Check start time
187
- if (occ_start_time - start_time) > max_hrs || (start_time - occ_start_time) > max_hrs
188
- check_elems << OpenStudio::Attribute.new('flag', "The start time of #{coord_sch.name} is #{start_time}, which is more than #{max_hrs} away from the occupancy schedule start time of #{occ_start_time} for #{occ_schs[0].name} in #{space.name}. Schedules do not coordinate.")
189
- end
190
-
191
- # Check end time
192
- if (occ_end_time - end_time) > max_hrs || (end_time - occ_end_time) > max_hrs
193
- check_elems << OpenStudio::Attribute.new('flag', "The end time of #{coord_sch.name} is #{end_time}, which is more than #{max_hrs} away from the occupancy schedule end time of #{occ_end_time} for #{occ_schs[0].name} in #{space.name}. Schedules do not coordinate.")
194
- end
195
- end
196
- end
197
- rescue StandardError => e
198
- # brief description of ruby error
199
- check_elems << OpenStudio::Attribute.new('flag', "Error prevented QAQC check from running (#{e}).")
200
-
201
- # backtrace of ruby error for diagnostic use
202
- if @error_backtrace then check_elems << OpenStudio::Attribute.new('flag', e.backtrace.join("\n").to_s) end
203
- end
204
-
205
- # add check_elms to new attribute
206
- check_elem = OpenStudio::Attribute.new('check', check_elems)
207
-
208
- return check_elem
209
- # note: registerWarning and registerValue will be added for checks downstream using os_lib_reporting_qaqc.rb
210
- end
211
- end