Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix schedule processing error for Appendix G #1687

Merged
merged 16 commits into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions lib/openstudio-standards/schedules/modify.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ def self.schedule_ruleset_add_rule(schedule_ruleset, values,
return sch_rule
end

# Increase/decrease by percentage or static value
# Increase/decrease by percentage or static value.
# If the schedule has a scheduleTypeLimits object, the adjusted values will subject to the lower and upper bounds of the schedule type limits object.
#
# @param schedule_ruleset [OpenStudio::Model::ScheduleRuleset] OpenStudio ScheduleRuleset object
# @param value [Double] Hash of name and time value pairs
Expand All @@ -105,6 +106,19 @@ def self.schedule_ruleset_add_rule(schedule_ruleset, values,
def self.schedule_ruleset_simple_value_adjust(schedule_ruleset, value, modification_type = 'Multiplier')
# gather profiles
profiles = []
# positive infinity
upper_bound = Float::INFINITY
# negative infinity
lower_bound = -upper_bound
if schedule_ruleset.scheduleTypeLimits.is_initialized
scheduleTypeLimits = schedule_ruleset.scheduleTypeLimits.get
if scheduleTypeLimits.lowerLimitValue.is_initialized
lower_bound = scheduleTypeLimits.lowerLimitValue.get
end
if scheduleTypeLimits.upperLimitValue.is_initialized
upper_bound = scheduleTypeLimits.upperLimitValue.get
end
end
default_profile = schedule_ruleset.to_ScheduleRuleset.get.defaultDaySchedule
profiles << default_profile
rules = schedule_ruleset.scheduleRules
Expand All @@ -120,10 +134,12 @@ def self.schedule_ruleset_simple_value_adjust(schedule_ruleset, value, modificat
case modification_type
when 'Multiplier', 'Percentage'
# percentage was used early on but Multiplier is preferable
profile.addValue(times[i], sch_value * value)
new_value = [lower_bound, [upper_bound, sch_value * value].min].max
profile.addValue(times[i], new_value)
when 'Sum', 'Value'
# value was used early on but Sum is preferable
profile.addValue(times[i], sch_value + value)
new_value = [lower_bound, [upper_bound, sch_value + value].min].max
profile.addValue(times[i], new_value)
end
i += 1
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -510,64 +510,23 @@ def space_type_light_sch_change(model)

def deep_copy_schedule(new_schedule_name, schedule, adjustment_factor, model)
OpenStudio.logFree(OpenStudio::Info, 'prm.log', "Creating a new lighting schedule that applies occupancy sensor adjustment factor: #{adjustment_factor} based on #{schedule.name.get} schedule")
ruleset = OpenStudio::Model::ScheduleRuleset.new(model)
ruleset.setName(new_schedule_name)

# schedule types limits and default day schedule - keep the copy
schedule_ruleset = prm_get_optional_handler(schedule, @sizing_run_dir, 'to_ScheduleRuleset')
schedule_type_limit = prm_get_optional_handler(schedule, @sizing_run_dir, 'scheduleTypeLimits')
default_day_schedule = schedule_ruleset.defaultDaySchedule
default_winter_design_day_schedule = schedule_ruleset.winterDesignDaySchedule
default_summer_design_day_schedule = schedule_ruleset.summerDesignDaySchedule

schedule_ruleset.scheduleRules.each do |week_rule|
day_rule = week_rule.daySchedule
start_date = prm_get_optional_handler(week_rule, @sizing_run_dir, 'startDate')
end_date = prm_get_optional_handler(week_rule, @sizing_run_dir, 'endDate')

# create a new day rule - copy and apply the ajustment factor
new_day_rule = OpenStudio::Model::ScheduleDay.new(model)
new_day_rule.setName(format("#{day_rule.name.get}_%.4f", adjustment_factor))
new_day_rule.setScheduleTypeLimits(schedule_type_limit)

# process day rule
times = day_rule.times()
# remove the effect of occupancy sensors
times.each do |time|
hour_value = day_rule.getValue(time)
new_value = hour_value / (1.0 - adjustment_factor.to_f)
if new_value > 1
new_day_rule.addValue(time, 1.0)
else
new_day_rule.addValue(time, new_value)
end
end

# create week rule schedule
new_week_rule = OpenStudio::Model::ScheduleRule.new(ruleset, new_day_rule)
new_week_rule.setName(format("#{week_rule.name.get}_%.4f", adjustment_factor))
new_week_rule.setApplySunday(week_rule.applySunday)
new_week_rule.setApplyMonday(week_rule.applyMonday)
new_week_rule.setApplyTuesday(week_rule.applyTuesday)
new_week_rule.setApplyWednesday(week_rule.applyWednesday)
new_week_rule.setApplyThursday(week_rule.applyThursday)
new_week_rule.setApplyFriday(week_rule.applyFriday)
new_week_rule.setApplySaturday(week_rule.applySaturday)
new_week_rule.setStartDate(start_date)
new_week_rule.setEndDate(end_date)
sch = OpenstudioStandards::Schedules
multiplier = 1.0 / (1.0 - adjustment_factor.to_f)
case schedule.iddObjectType.valueName.to_s
when 'OS_Schedule_Constant'
schedule_constant = schedule.to_ScheduleConstant.get
schedule_value = schedule_constant.value
return sch.create_constant_schedule_ruleset(model, schedule_value * multiplier, name: new_schedule_name)
when 'OS_Schedule_Ruleset'
new_schedule = schedule.clone(model)
new_schedule.setName(new_schedule_name)
schedule_ruleset = new_schedule.to_ScheduleRuleset.get
return sch.schedule_ruleset_simple_value_adjust(schedule_ruleset, multiplier, modification_type = 'Multiplier')
when 'OS_Schedule_Compact'
prm_raise(false, @sizing_run_dir, 'PRM does not support using Compact schedule for lighting schedules. Please update it to ruleset based or constant schedules.')
else
prm_raise(false, @sizing_run_dir, 'PRM only supports ruleset based or constant schedules for lighting schedules')
end
# default day schedule
default_day = ruleset.defaultDaySchedule
default_day.clearValues
default_day.times.each_index { |counter| default_day.addValue(default_day_schedule.times[counter], default_day_schedule.values[counter]) }
# winter design day schedule
winter_design_day_schedule = ruleset.winterDesignDaySchedule
winter_design_day_schedule.clearValues
winter_design_day_schedule.times.each_index { |counter| winter_design_day_schedule.addValue(default_winter_design_day_schedule.times[counter], default_winter_design_day_schedule.values[counter]) }
summer_design_day_schedule = ruleset.summerDesignDaySchedule
summer_design_day_schedule.clearValues
summer_design_day_schedule.times.each_index { |counter| summer_design_day_schedule.addValue(default_summer_design_day_schedule.times[counter], default_summer_design_day_schedule.values[counter]) }
return ruleset
end

# calculate the lighting power density per area based on space type
Expand Down
34 changes: 18 additions & 16 deletions test/90_1_prm/data/prototype_list.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
"daylighting_control": [
["SmallOffice", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", []]
],
"dcv": [
"dcv_01": [
["PrimarySchool", "90.1-2019", "ASHRAE 169-2013-4A", "userdata_default_test", [["remove_transformer", []], ["change_zone_num_ppl", ["Cafeteria_ZN_1_FLR_1 ZN", 400]], ["enable_airloop_dcv", ["Cafeteria_ZN_1_FLR_1 ZN PSZ-AC_2-7"]], ["mark_test_case_no", [1, 8]]]],
["PrimarySchool", "90.1-2019", "ASHRAE 169-2013-4A", "dcv_userdata_cafeteria_zone_exception", [["remove_transformer", []], ["change_zone_num_ppl", ["Cafeteria_ZN_1_FLR_1 ZN", 400]], ["enable_airloop_dcv", ["Cafeteria_ZN_1_FLR_1 ZN PSZ-AC_2-7"]], ["mark_test_case_no", [2]]]],
["PrimarySchool", "90.1-2019", "ASHRAE 169-2013-4A", "userdata_default_test", [["remove_transformer", []], ["change_zone_num_ppl", ["Cafeteria_ZN_1_FLR_1 ZN", 400]], ["enable_airloop_dcv", ["Kitchen_ZN_1_FLR_1 ZN PSZ-AC_1-6"]], ["mark_test_case_no", [3, 7]]]],
["PrimarySchool", "90.1-2019", "ASHRAE 169-2013-4A", "userdata_default_test", [["remove_transformer", []], ["change_zone_num_ppl", ["Cafeteria_ZN_1_FLR_1 ZN", 400]], ["enable_airloop_dcv", ["Kitchen_ZN_1_FLR_1 ZN PSZ-AC_1-6"]], ["mark_test_case_no", [3, 7]]]]
],
"dcv_02": [
["PrimarySchool", "90.1-2019", "ASHRAE 169-2013-4A", "dcv_userdata_cafeteria_airloop_exception", [["remove_transformer", []], ["change_zone_num_ppl", ["Cafeteria_ZN_1_FLR_1 ZN", 400]], ["mark_test_case_no", [4]]]],
["PrimarySchool", "90.1-2019", "ASHRAE 169-2013-4A", "userdata_default_test", [["remove_transformer", []], ["enable_airloop_dcv", ["Cafeteria_ZN_1_FLR_1 ZN PSZ-AC_2-7"]], ["mark_test_case_no", [5]]]],
["PrimarySchool", "90.1-2019", "ASHRAE 169-2013-4A", "dcv_userdata_cafeteria_zone_exception", [["remove_transformer", []], ["mark_test_case_no", [6]]]]
Expand Down Expand Up @@ -68,8 +70,6 @@
"hvac_baseline_03": [
["PrimarySchool", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", [["remove_transformer", []]]],
["PrimarySchool", "90.1-2013", "ASHRAE 169-2013-4A", "userdata_default_test", [["remove_transformer", []]]],
["SecondarySchool", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", [["remove_transformer", []]]],
["SecondarySchool", "90.1-2013", "ASHRAE 169-2013-4A", "userdata_default_test", [["remove_transformer", []]]],
["SmallOffice", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", [["set_zone_multiplier",[4]]]],
["SmallOffice", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", [["set_zone_multiplier",[5]]]]
],
Expand Down Expand Up @@ -100,17 +100,20 @@
["MediumOffice", "90.1-2004", "ASHRAE 169-2013-2A", "userdata_default_test", [["remove_transformer", []],["change_zone_epd", ["Perimeter_bot_ZN_1 ZN",70]]]],
["MediumOffice", "90.1-2004", "ASHRAE 169-2013-2A", "userdata_default_test", [["remove_transformer", []],["change_to_long_occ_sch", ["Perimeter_bot_ZN_1 ZN"]]]]
],
"hvac_sizing": [
"hvac_sizing_01": [
["PrimarySchool", "90.1-2013", "ASHRAE 169-2013-4A", "userdata_default_test", [["remove_transformer", []]]],
["SecondarySchool", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", [["remove_transformer", []]]],
["MidriseApartment", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", []],
["LargeHotel", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", [["remove_transformer", []]]],
["RetailStripmall", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", []],
["RetailStandalone", "90.1-2010", "ASHRAE 169-2013-2A", "userdata_default_test", []],
["RetailStandalone", "90.1-2010", "ASHRAE 169-2013-2A", "userdata_default_test", []]
],
"hvac_sizing_02": [
["Warehouse", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", []],
["MediumOffice", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", [["remove_transformer", []]]],
["SmallOffice", "90.1-2013", "ASHRAE 169-2013-4A", "userdata_default_test", []],
["SmallOffice", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", [["convert_spaces_from_to", ["OfficeWholeBuilding - Sm Office", "laboratory"]]]],
["SmallOffice", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", [["convert_spaces_from_to", ["OfficeWholeBuilding - Sm Office", "laboratory"]]]]
],
"hvac_sizing_03": [
["LargeOffice", "90.1-2004", "ASHRAE 169-2013-2A", "userdata_default_test", [["remove_transformer", []]]]
],
"infiltration": [
Expand Down Expand Up @@ -167,22 +170,21 @@
["SmallOffice", "90.1-2004", "ASHRAE 169-2013-2B", "userdata_pe_04",[["remove_transformer", []]]]
],
"pipe_insulation": [

["QuickServiceRestaurant", "90.1-2019", "ASHRAE 169-2013-2A", "userdata_default_test", [["add_piping_insulation", []]]]
],
"plant_temp_reset_ctrl": [
["MidriseApartment", "90.1-2013", "ASHRAE 169-2013-4A", "userdata_default_test", []],
["PrimarySchool", "90.1-2013", "ASHRAE 169-2013-4A", "userdata_default_test", [["remove_transformer", []]]],
["SecondarySchool", "90.1-2013", "ASHRAE 169-2013-4A", "userdata_default_test", [["remove_transformer", []]]],
"plant_temp_reset_ctrl_01": [
["SecondarySchool", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", [["remove_transformer", []]]],
["LargeHotel", "90.1-2013", "ASHRAE 169-2013-4A", "userdata_default_test", [["change_bldg_type", ["Assembly"]], ["remove_transformer", []]]],
["LargeHotel", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", [["change_bldg_type", ["Assembly"]], ["remove_transformer", []]]]
],
"plant_temp_reset_ctrl_02": [
["MidriseApartment", "90.1-2013", "ASHRAE 169-2013-4A", "userdata_default_test", []],
["PrimarySchool", "90.1-2013", "ASHRAE 169-2013-4A", "userdata_default_test", [["remove_transformer", []]]],
["SecondarySchool", "90.1-2013", "ASHRAE 169-2013-4A", "userdata_default_test", [["remove_transformer", []]]]
],
"preheat_coil_ctrl": [
["PrimarySchool", "90.1-2013", "ASHRAE 169-2013-4A", "userdata_default_test", [["remove_transformer", []]]],
["PrimarySchool", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", [["remove_transformer", []]]],
["SecondarySchool", "90.1-2013", "ASHRAE 169-2013-4A", "userdata_default_test", [["remove_transformer", []]]],
["SecondarySchool", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", [["remove_transformer", []]]]
["PrimarySchool", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_default_test", [["remove_transformer", []]]]
],
"proposed_model_residential_lpd": [
["LargeHotel", "90.1-2013", "ASHRAE 169-2013-2A", "userdata_res_ltg", [["remove_transformer", []], ["reduce_lpd" , []]]]
Expand Down
Loading