diff --git a/measures/ResStockArgumentsPostHPXML/measure.rb b/measures/ResStockArgumentsPostHPXML/measure.rb index ace3a59a9b..8e0d7e435b 100644 --- a/measures/ResStockArgumentsPostHPXML/measure.rb +++ b/measures/ResStockArgumentsPostHPXML/measure.rb @@ -33,29 +33,22 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument arg.setDescription('Absolute/relative path of the HPXML file.') args << arg - # Add args for flexibility inputs. Use hours format for the duration and minutes for the random offset. Offsets are degree F. - arg = OpenStudio::Measure::OSArgument.makeDoubleArgument('loadflex_peak_duration_hours', false) - arg.setDisplayName('Load Flexibility: Peak Duration (hours)') - arg.setDescription('Duration of the peak period in hours.') - arg.setDefaultValue(0) - args << arg - arg = OpenStudio::Measure::OSArgument.makeIntegerArgument('loadflex_peak_offset', false) arg.setDisplayName('Load Flexibility: Peak Offset (deg F)') arg.setDescription('Offset of the peak period in degrees Fahrenheit.') - arg.setDefaultValue(0) + arg.setDefaultValue(2) args << arg arg = OpenStudio::Measure::OSArgument.makeDoubleArgument('loadflex_pre_peak_duration_hours', false) arg.setDisplayName('Load Flexibility: Pre-Peak Duration (hours)') arg.setDescription('Duration of the pre-peak period in hours.') - arg.setDefaultValue(0) + arg.setDefaultValue(2) args << arg arg = OpenStudio::Measure::OSArgument.makeIntegerArgument('loadflex_pre_peak_offset', false) arg.setDisplayName('Load Flexibility: Pre-Peak Offset (deg F)') arg.setDescription('Offset of the pre-peak period in degrees Fahrenheit.') - arg.setDefaultValue(0) + arg.setDefaultValue(3) args << arg arg = OpenStudio::Measure::OSArgument.makeIntegerArgument('loadflex_random_shift_minutes', false) @@ -123,7 +116,7 @@ def run(model, runner, user_arguments) end def skip_load_flexibility?(args) - args[:loadflex_peak_duration_hours] == 0 && args[:loadflex_pre_peak_duration_hours] == 0 + args[:loadflex_peak_offset] == 0 && args[:loadflex_pre_peak_duration_hours] == 0 end def create_schedule(hpxml, hpxml_path, runner, building_index) @@ -139,12 +132,17 @@ def modify_schedule(hpxml, building_index, args, runner, schedule) sim_year = hpxml.header.sim_calendar_year epw_path = Location.get_epw_path(hpxml_bldg, args[:hpxml_path]) weather = WeatherFile.new(epw_path: epw_path, runner: runner, hpxml: hpxml) + dst_info = DSTInfo.new(dst_begin_month: hpxml_bldg.dst_begin_month, + dst_begin_day: hpxml_bldg.dst_begin_day, + dst_end_month: hpxml_bldg.dst_end_month, + dst_end_day: hpxml_bldg.dst_end_day) schedule_modifier = HVACScheduleModifier.new(state: state, sim_year: sim_year, weather: weather, epw_path: epw_path, minutes_per_step: minutes_per_step, - runner: runner) + runner: runner, + dst_info: dst_info) flexibility_inputs = get_flexibility_inputs(args, minutes_per_step, building_id) schedule_modifier.modify_setpoints(schedule, flexibility_inputs) end @@ -154,7 +152,6 @@ def get_flexibility_inputs(args, minutes_per_step, building_id) max_random_shift_steps = (args[:loadflex_random_shift_minutes] / minutes_per_step).to_i random_shift_steps = rand(-max_random_shift_steps..max_random_shift_steps) FlexibilityInputs.new( - peak_duration_steps: (args[:loadflex_peak_duration_hours] * 60 / minutes_per_step).to_i, peak_offset: args[:loadflex_peak_offset], pre_peak_duration_steps: (args[:loadflex_pre_peak_duration_hours] * 60 / minutes_per_step).to_i, pre_peak_offset: args[:loadflex_pre_peak_offset], diff --git a/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/detailed_schedule_generator.rb b/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/detailed_schedule_generator.rb index b7274fb5d4..be4e8b3f1e 100644 --- a/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/detailed_schedule_generator.rb +++ b/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/detailed_schedule_generator.rb @@ -68,7 +68,7 @@ def get_heating_cooling_weekday_weekend_setpoints hvac_control = @hpxml_bldg.hvac_controls[0] onoff_thermostat_ddb = @hpxml.header.hvac_onoff_thermostat_deadband.to_f htg_weekday_setpoints, htg_weekend_setpoints = HVAC.get_heating_setpoints(hvac_control, @sim_year, onoff_thermostat_ddb) - clg_weekday_setpoints, clg_weekend_setpoints = HVAC.get_cooling_setpoints(hvac_control, has_ceiling_fan, @sim_year, @weather, onoff_thermostat_ddb) + clg_weekday_setpoints, clg_weekend_setpoints = HVAC.get_cooling_setpoints(@hpxml_bldg, hvac_control, has_ceiling_fan, @sim_year, @weather, onoff_thermostat_ddb) htg_weekday_setpoints, htg_weekend_setpoints, clg_weekday_setpoints, clg_weekend_setpoints = HVAC.create_setpoint_schedules(@runner, htg_weekday_setpoints, htg_weekend_setpoints, clg_weekday_setpoints, clg_weekend_setpoints, @sim_year, hvac_season_days) return c2f(clg_weekday_setpoints), c2f(clg_weekend_setpoints), c2f(htg_weekday_setpoints), c2f(htg_weekend_setpoints) diff --git a/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/seasonal_shedding_peak_hours.json b/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/seasonal_shedding_peak_hours.json new file mode 100644 index 0000000000..78695b8232 --- /dev/null +++ b/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/seasonal_shedding_peak_hours.json @@ -0,0 +1,386 @@ +{ + "IA": { + "summer_peak_start": "2050-08-28 17:00:00", + "summer_peak_end": "2050-08-28 21:00:00", + "winter_peak_start": "2050-01-19 17:00:00", + "winter_peak_end": "2050-01-19 21:00:00", + "intermediate_peak_start": "2050-11-04 17:00:00", + "intermediate_peak_end": "2050-11-04 21:00:00" + }, + "WV": { + "summer_peak_start": "2050-07-18 16:00:00", + "summer_peak_end": "2050-07-18 20:00:00", + "winter_peak_start": "2050-01-18 17:00:00", + "winter_peak_end": "2050-01-18 21:00:00", + "intermediate_peak_start": "2050-05-29 16:00:00", + "intermediate_peak_end": "2050-05-29 20:00:00" + }, + "MA": { + "summer_peak_start": "2050-06-22 17:00:00", + "summer_peak_end": "2050-06-22 21:00:00", + "winter_peak_start": "2050-12-14 17:00:00", + "winter_peak_end": "2050-12-14 21:00:00", + "intermediate_peak_start": "2050-10-18 17:00:00", + "intermediate_peak_end": "2050-10-18 21:00:00" + }, + "VT": { + "summer_peak_start": "2050-07-12 18:00:00", + "summer_peak_end": "2050-07-12 22:00:00", + "winter_peak_start": "2050-12-25 18:00:00", + "winter_peak_end": "2050-12-25 22:00:00", + "intermediate_peak_start": "2050-11-28 17:00:00", + "intermediate_peak_end": "2050-11-28 21:00:00" + }, + "WI": { + "summer_peak_start": "2050-07-06 18:00:00", + "summer_peak_end": "2050-07-06 22:00:00", + "winter_peak_start": "2050-12-19 17:00:00", + "winter_peak_end": "2050-12-19 21:00:00", + "intermediate_peak_start": "2050-11-08 17:00:00", + "intermediate_peak_end": "2050-11-08 21:00:00" + }, + "CT": { + "summer_peak_start": "2050-06-22 17:00:00", + "summer_peak_end": "2050-06-22 21:00:00", + "winter_peak_start": "2050-12-07 17:00:00", + "winter_peak_end": "2050-12-07 21:00:00", + "intermediate_peak_start": "2050-05-30 17:00:00", + "intermediate_peak_end": "2050-05-30 21:00:00" + }, + "TN": { + "summer_peak_start": "2050-06-30 17:00:00", + "summer_peak_end": "2050-06-30 21:00:00", + "winter_peak_start": "2050-01-18 17:00:00", + "winter_peak_end": "2050-01-18 21:00:00", + "intermediate_peak_start": "2050-05-28 17:00:00", + "intermediate_peak_end": "2050-05-28 21:00:00" + }, + "NY": { + "summer_peak_start": "2050-07-06 18:00:00", + "summer_peak_end": "2050-07-06 22:00:00", + "winter_peak_start": "2050-01-20 17:00:00", + "winter_peak_end": "2050-01-20 21:00:00", + "intermediate_peak_start": "2050-11-16 17:00:00", + "intermediate_peak_end": "2050-11-16 21:00:00" + }, + "UT": { + "summer_peak_start": "2050-08-08 18:00:00", + "summer_peak_end": "2050-08-08 22:00:00", + "winter_peak_start": "2050-12-29 17:00:00", + "winter_peak_end": "2050-12-29 21:00:00", + "intermediate_peak_start": "2050-11-13 17:00:00", + "intermediate_peak_end": "2050-11-13 21:00:00" + }, + "VA": { + "summer_peak_start": "2050-07-07 18:00:00", + "summer_peak_end": "2050-07-07 22:00:00", + "winter_peak_start": "2050-12-29 16:00:00", + "winter_peak_end": "2050-12-29 20:00:00", + "intermediate_peak_start": "2050-11-27 16:00:00", + "intermediate_peak_end": "2050-11-27 20:00:00" + }, + "SD": { + "summer_peak_start": "2050-06-29 15:00:00", + "summer_peak_end": "2050-06-29 19:00:00", + "winter_peak_start": "2050-12-26 16:00:00", + "winter_peak_end": "2050-12-26 20:00:00", + "intermediate_peak_start": "2050-04-17 18:00:00", + "intermediate_peak_end": "2050-04-17 22:00:00" + }, + "OH": { + "summer_peak_start": "2050-07-07 17:00:00", + "summer_peak_end": "2050-07-07 21:00:00", + "winter_peak_start": "2050-01-03 17:00:00", + "winter_peak_end": "2050-01-03 21:00:00", + "intermediate_peak_start": "2050-11-28 17:00:00", + "intermediate_peak_end": "2050-11-28 21:00:00" + }, + "SC": { + "summer_peak_start": "2050-07-28 19:00:00", + "summer_peak_end": "2050-07-28 23:00:00", + "winter_peak_start": "2050-02-09 18:00:00", + "winter_peak_end": "2050-02-09 22:00:00", + "intermediate_peak_start": "2050-10-05 17:00:00", + "intermediate_peak_end": "2050-10-05 21:00:00" + }, + "MT": { + "summer_peak_start": "2050-09-25 17:00:00", + "summer_peak_end": "2050-09-25 21:00:00", + "winter_peak_start": "2050-01-18 18:00:00", + "winter_peak_end": "2050-01-18 22:00:00", + "intermediate_peak_start": "2050-10-06 19:00:00", + "intermediate_peak_end": "2050-10-06 23:00:00" + }, + "MS": { + "summer_peak_start": "2050-07-30 18:00:00", + "summer_peak_end": "2050-07-30 22:00:00", + "winter_peak_start": "2050-01-18 17:00:00", + "winter_peak_end": "2050-01-18 21:00:00", + "intermediate_peak_start": "2050-05-28 18:00:00", + "intermediate_peak_end": "2050-05-28 22:00:00" + }, + "NM": { + "summer_peak_start": "2050-08-09 18:00:00", + "summer_peak_end": "2050-08-09 22:00:00", + "winter_peak_start": "2050-03-11 17:00:00", + "winter_peak_end": "2050-03-11 21:00:00", + "intermediate_peak_start": "2050-10-31 17:00:00", + "intermediate_peak_end": "2050-10-31 21:00:00" + }, + "NJ": { + "summer_peak_start": "2050-07-06 17:00:00", + "summer_peak_end": "2050-07-06 21:00:00", + "winter_peak_start": "2050-12-07 17:00:00", + "winter_peak_end": "2050-12-07 21:00:00", + "intermediate_peak_start": "2050-05-31 17:00:00", + "intermediate_peak_end": "2050-05-31 21:00:00" + }, + "GA": { + "summer_peak_start": "2050-06-30 18:00:00", + "summer_peak_end": "2050-06-30 22:00:00", + "winter_peak_start": "2050-01-03 18:00:00", + "winter_peak_end": "2050-01-03 22:00:00", + "intermediate_peak_start": "2050-05-26 18:00:00", + "intermediate_peak_end": "2050-05-26 22:00:00" + }, + "CA": { + "summer_peak_start": "2050-08-14 18:00:00", + "summer_peak_end": "2050-08-14 22:00:00", + "winter_peak_start": "2050-12-14 17:00:00", + "winter_peak_end": "2050-12-14 21:00:00", + "intermediate_peak_start": "2050-10-02 17:00:00", + "intermediate_peak_end": "2050-10-02 21:00:00" + }, + "IL": { + "summer_peak_start": "2050-07-07 18:00:00", + "summer_peak_end": "2050-07-07 22:00:00", + "winter_peak_start": "2050-12-29 16:00:00", + "winter_peak_end": "2050-12-29 20:00:00", + "intermediate_peak_start": "2050-11-08 16:00:00", + "intermediate_peak_end": "2050-11-08 20:00:00" + }, + "AZ": { + "summer_peak_start": "2050-08-09 18:00:00", + "summer_peak_end": "2050-08-09 22:00:00", + "winter_peak_start": "2050-03-30 18:00:00", + "winter_peak_end": "2050-03-30 22:00:00", + "intermediate_peak_start": "2050-10-03 17:00:00", + "intermediate_peak_end": "2050-10-03 21:00:00" + }, + "TX": { + "summer_peak_start": "2050-08-28 18:00:00", + "summer_peak_end": "2050-08-28 22:00:00", + "winter_peak_start": "2050-12-12 17:00:00", + "winter_peak_end": "2050-12-12 21:00:00", + "intermediate_peak_start": "2050-10-03 17:00:00", + "intermediate_peak_end": "2050-10-03 21:00:00" + }, + "NH": { + "summer_peak_start": "2050-08-09 17:00:00", + "summer_peak_end": "2050-08-09 21:00:00", + "winter_peak_start": "2050-12-07 17:00:00", + "winter_peak_end": "2050-12-07 21:00:00", + "intermediate_peak_start": "2050-11-28 17:00:00", + "intermediate_peak_end": "2050-11-28 21:00:00" + }, + "DE": { + "summer_peak_start": "2050-06-30 17:00:00", + "summer_peak_end": "2050-06-30 21:00:00", + "winter_peak_start": "2050-12-07 17:00:00", + "winter_peak_end": "2050-12-07 21:00:00", + "intermediate_peak_start": "2050-11-27 17:00:00", + "intermediate_peak_end": "2050-11-27 21:00:00" + }, + "WA": { + "summer_peak_start": "2050-08-17 17:00:00", + "summer_peak_end": "2050-08-17 21:00:00", + "winter_peak_start": "2050-01-12 17:00:00", + "winter_peak_end": "2050-01-12 21:00:00", + "intermediate_peak_start": "2050-10-25 17:00:00", + "intermediate_peak_end": "2050-10-25 21:00:00" + }, + "OR": { + "summer_peak_start": "2050-09-18 17:00:00", + "summer_peak_end": "2050-09-18 21:00:00", + "winter_peak_start": "2050-01-12 17:00:00", + "winter_peak_end": "2050-01-12 21:00:00", + "intermediate_peak_start": "2050-10-26 16:00:00", + "intermediate_peak_end": "2050-10-26 20:00:00" + }, + "MI": { + "summer_peak_start": "2050-07-07 17:00:00", + "summer_peak_end": "2050-07-07 21:00:00", + "winter_peak_start": "2050-03-02 18:00:00", + "winter_peak_end": "2050-03-02 22:00:00", + "intermediate_peak_start": "2050-11-21 17:00:00", + "intermediate_peak_end": "2050-11-21 21:00:00" + }, + "MN": { + "summer_peak_start": "2050-07-15 17:00:00", + "summer_peak_end": "2050-07-15 21:00:00", + "winter_peak_start": "2050-12-12 17:00:00", + "winter_peak_end": "2050-12-12 21:00:00", + "intermediate_peak_start": "2050-11-04 16:00:00", + "intermediate_peak_end": "2050-11-04 20:00:00" + }, + "WY": { + "summer_peak_start": "2050-09-18 18:00:00", + "summer_peak_end": "2050-09-18 22:00:00", + "winter_peak_start": "2050-02-07 08:00:00", + "winter_peak_end": "2050-02-07 12:00:00", + "intermediate_peak_start": "2050-10-26 08:00:00", + "intermediate_peak_end": "2050-10-26 12:00:00" + }, + "IN": { + "summer_peak_start": "2050-07-07 18:00:00", + "summer_peak_end": "2050-07-07 22:00:00", + "winter_peak_start": "2050-12-28 17:00:00", + "winter_peak_end": "2050-12-28 21:00:00", + "intermediate_peak_start": "2050-11-14 17:00:00", + "intermediate_peak_end": "2050-11-14 21:00:00" + }, + "OK": { + "summer_peak_start": "2050-09-06 15:00:00", + "summer_peak_end": "2050-09-06 19:00:00", + "winter_peak_start": "2050-02-14 04:00:00", + "winter_peak_end": "2050-02-14 08:00:00", + "intermediate_peak_start": "2050-11-17 03:00:00", + "intermediate_peak_end": "2050-11-17 07:00:00" + }, + "NV": { + "summer_peak_start": "2050-07-11 18:00:00", + "summer_peak_end": "2050-07-11 22:00:00", + "winter_peak_start": "2050-12-29 17:00:00", + "winter_peak_end": "2050-12-29 21:00:00", + "intermediate_peak_start": "2050-05-17 18:00:00", + "intermediate_peak_end": "2050-05-17 22:00:00" + }, + "KS": { + "summer_peak_start": "2050-08-01 18:00:00", + "summer_peak_end": "2050-08-01 22:00:00", + "winter_peak_start": "2050-01-17 17:00:00", + "winter_peak_end": "2050-01-17 21:00:00", + "intermediate_peak_start": "2050-11-01 17:00:00", + "intermediate_peak_end": "2050-11-01 21:00:00" + }, + "PA": { + "summer_peak_start": "2050-06-22 17:00:00", + "summer_peak_end": "2050-06-22 21:00:00", + "winter_peak_start": "2050-01-03 17:00:00", + "winter_peak_end": "2050-01-03 21:00:00", + "intermediate_peak_start": "2050-05-29 17:00:00", + "intermediate_peak_end": "2050-05-29 21:00:00" + }, + "MO": { + "summer_peak_start": "2050-07-06 18:00:00", + "summer_peak_end": "2050-07-06 22:00:00", + "winter_peak_start": "2050-12-29 08:00:00", + "winter_peak_end": "2050-12-29 12:00:00", + "intermediate_peak_start": "2050-11-16 16:00:00", + "intermediate_peak_end": "2050-11-16 20:00:00" + }, + "ME": { + "summer_peak_start": "2050-08-10 17:00:00", + "summer_peak_end": "2050-08-10 21:00:00", + "winter_peak_start": "2050-02-15 17:00:00", + "winter_peak_end": "2050-02-15 21:00:00", + "intermediate_peak_start": "2050-11-28 16:00:00", + "intermediate_peak_end": "2050-11-28 20:00:00" + }, + "KY": { + "summer_peak_start": "2050-07-07 19:00:00", + "summer_peak_end": "2050-07-07 23:00:00", + "winter_peak_start": "2050-12-12 17:00:00", + "winter_peak_end": "2050-12-12 21:00:00", + "intermediate_peak_start": "2050-11-29 17:00:00", + "intermediate_peak_end": "2050-11-29 21:00:00" + }, + "CO": { + "summer_peak_start": "2050-08-09 18:00:00", + "summer_peak_end": "2050-08-09 22:00:00", + "winter_peak_start": "2050-12-26 18:00:00", + "winter_peak_end": "2050-12-26 22:00:00", + "intermediate_peak_start": "2050-11-27 16:00:00", + "intermediate_peak_end": "2050-11-27 20:00:00" + }, + "NC": { + "summer_peak_start": "2050-08-16 18:00:00", + "summer_peak_end": "2050-08-16 22:00:00", + "winter_peak_start": "2050-12-29 17:00:00", + "winter_peak_end": "2050-12-29 21:00:00", + "intermediate_peak_start": "2050-11-30 17:00:00", + "intermediate_peak_end": "2050-11-30 21:00:00" + }, + "AL": { + "summer_peak_start": "2050-07-24 18:00:00", + "summer_peak_end": "2050-07-24 22:00:00", + "winter_peak_start": "2050-01-03 18:00:00", + "winter_peak_end": "2050-01-03 22:00:00", + "intermediate_peak_start": "2050-05-26 18:00:00", + "intermediate_peak_end": "2050-05-26 22:00:00" + }, + "ND": { + "summer_peak_start": "2050-07-31 19:00:00", + "summer_peak_end": "2050-07-31 23:00:00", + "winter_peak_start": "2050-12-26 19:00:00", + "winter_peak_end": "2050-12-26 23:00:00", + "intermediate_peak_start": "2050-04-17 18:00:00", + "intermediate_peak_end": "2050-04-17 22:00:00" + }, + "AR": { + "summer_peak_start": "2050-09-06 17:00:00", + "summer_peak_end": "2050-09-06 21:00:00", + "winter_peak_start": "2050-12-12 17:00:00", + "winter_peak_end": "2050-12-12 21:00:00", + "intermediate_peak_start": "2050-05-30 18:00:00", + "intermediate_peak_end": "2050-05-30 22:00:00" + }, + "FL": { + "summer_peak_start": "2050-07-27 18:00:00", + "summer_peak_end": "2050-07-27 22:00:00", + "winter_peak_start": "2050-01-03 18:00:00", + "winter_peak_end": "2050-01-03 22:00:00", + "intermediate_peak_start": "2050-05-31 18:00:00", + "intermediate_peak_end": "2050-05-31 22:00:00" + }, + "ID": { + "summer_peak_start": "2050-08-05 19:00:00", + "summer_peak_end": "2050-08-05 23:00:00", + "winter_peak_start": "2050-01-12 17:00:00", + "winter_peak_end": "2050-01-12 21:00:00", + "intermediate_peak_start": "2050-11-15 18:00:00", + "intermediate_peak_end": "2050-11-15 22:00:00" + }, + "LA": { + "summer_peak_start": "2050-06-29 18:00:00", + "summer_peak_end": "2050-06-29 22:00:00", + "winter_peak_start": "2050-12-12 17:00:00", + "winter_peak_end": "2050-12-12 21:00:00", + "intermediate_peak_start": "2050-05-30 18:00:00", + "intermediate_peak_end": "2050-05-30 22:00:00" + }, + "MD": { + "summer_peak_start": "2050-07-06 17:00:00", + "summer_peak_end": "2050-07-06 21:00:00", + "winter_peak_start": "2050-01-09 16:00:00", + "winter_peak_end": "2050-01-09 20:00:00", + "intermediate_peak_start": "2050-05-26 17:00:00", + "intermediate_peak_end": "2050-05-26 21:00:00" + }, + "NE": { + "summer_peak_start": "2050-07-15 15:00:00", + "summer_peak_end": "2050-07-15 19:00:00", + "winter_peak_start": "2050-03-16 17:00:00", + "winter_peak_end": "2050-03-16 21:00:00", + "intermediate_peak_start": "2050-10-31 16:00:00", + "intermediate_peak_end": "2050-10-31 20:00:00" + }, + "RI": { + "summer_peak_start": "2050-07-28 18:00:00", + "summer_peak_end": "2050-07-28 22:00:00", + "winter_peak_start": "2050-12-07 17:00:00", + "winter_peak_end": "2050-12-07 21:00:00", + "intermediate_peak_start": "2050-10-18 18:00:00", + "intermediate_peak_end": "2050-10-18 22:00:00" + } +} \ No newline at end of file diff --git a/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/seasonal_shifting_peak_hours.json b/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/seasonal_shifting_peak_hours.json new file mode 100644 index 0000000000..1a2c8b5066 --- /dev/null +++ b/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/seasonal_shifting_peak_hours.json @@ -0,0 +1,386 @@ +{ + "IA": { + "summer_peak_start": "2050-08-28 16:00:00", + "summer_peak_end": "2050-08-28 20:00:00", + "winter_peak_start": "2050-01-19 16:00:00", + "winter_peak_end": "2050-01-19 20:00:00", + "intermediate_peak_start": "2050-11-04 17:00:00", + "intermediate_peak_end": "2050-11-04 21:00:00" + }, + "WV": { + "summer_peak_start": "2050-07-18 16:00:00", + "summer_peak_end": "2050-07-18 20:00:00", + "winter_peak_start": "2050-01-18 16:00:00", + "winter_peak_end": "2050-01-18 20:00:00", + "intermediate_peak_start": "2050-05-29 16:00:00", + "intermediate_peak_end": "2050-05-29 20:00:00" + }, + "MA": { + "summer_peak_start": "2050-06-22 16:00:00", + "summer_peak_end": "2050-06-22 20:00:00", + "winter_peak_start": "2050-12-14 16:00:00", + "winter_peak_end": "2050-12-14 20:00:00", + "intermediate_peak_start": "2050-11-07 16:00:00", + "intermediate_peak_end": "2050-11-07 20:00:00" + }, + "VT": { + "summer_peak_start": "2050-07-12 17:00:00", + "summer_peak_end": "2050-07-12 21:00:00", + "winter_peak_start": "2050-12-07 15:00:00", + "winter_peak_end": "2050-12-07 19:00:00", + "intermediate_peak_start": "2050-11-28 16:00:00", + "intermediate_peak_end": "2050-11-28 20:00:00" + }, + "WI": { + "summer_peak_start": "2050-07-06 17:00:00", + "summer_peak_end": "2050-07-06 21:00:00", + "winter_peak_start": "2050-12-19 16:00:00", + "winter_peak_end": "2050-12-19 20:00:00", + "intermediate_peak_start": "2050-11-08 16:00:00", + "intermediate_peak_end": "2050-11-08 20:00:00" + }, + "CT": { + "summer_peak_start": "2050-06-22 16:00:00", + "summer_peak_end": "2050-06-22 20:00:00", + "winter_peak_start": "2050-12-07 16:00:00", + "winter_peak_end": "2050-12-07 20:00:00", + "intermediate_peak_start": "2050-05-30 17:00:00", + "intermediate_peak_end": "2050-05-30 21:00:00" + }, + "TN": { + "summer_peak_start": "2050-06-30 16:00:00", + "summer_peak_end": "2050-06-30 20:00:00", + "winter_peak_start": "2050-01-18 16:00:00", + "winter_peak_end": "2050-01-18 20:00:00", + "intermediate_peak_start": "2050-05-28 16:00:00", + "intermediate_peak_end": "2050-05-28 20:00:00" + }, + "NY": { + "summer_peak_start": "2050-07-06 17:00:00", + "summer_peak_end": "2050-07-06 21:00:00", + "winter_peak_start": "2050-01-20 17:00:00", + "winter_peak_end": "2050-01-20 21:00:00", + "intermediate_peak_start": "2050-11-16 16:00:00", + "intermediate_peak_end": "2050-11-16 20:00:00" + }, + "UT": { + "summer_peak_start": "2050-08-08 17:00:00", + "summer_peak_end": "2050-08-08 21:00:00", + "winter_peak_start": "2050-12-29 16:00:00", + "winter_peak_end": "2050-12-29 20:00:00", + "intermediate_peak_start": "2050-11-13 16:00:00", + "intermediate_peak_end": "2050-11-13 20:00:00" + }, + "VA": { + "summer_peak_start": "2050-07-07 17:00:00", + "summer_peak_end": "2050-07-07 21:00:00", + "winter_peak_start": "2050-12-29 16:00:00", + "winter_peak_end": "2050-12-29 20:00:00", + "intermediate_peak_start": "2050-05-04 16:00:00", + "intermediate_peak_end": "2050-05-04 20:00:00" + }, + "SD": { + "summer_peak_start": "2050-07-20 19:00:00", + "summer_peak_end": "2050-07-20 23:00:00", + "winter_peak_start": "2050-02-11 16:00:00", + "winter_peak_end": "2050-02-11 20:00:00", + "intermediate_peak_start": "2050-04-10 17:00:00", + "intermediate_peak_end": "2050-04-10 21:00:00" + }, + "OH": { + "summer_peak_start": "2050-07-07 17:00:00", + "summer_peak_end": "2050-07-07 21:00:00", + "winter_peak_start": "2050-01-03 16:00:00", + "winter_peak_end": "2050-01-03 20:00:00", + "intermediate_peak_start": "2050-11-28 16:00:00", + "intermediate_peak_end": "2050-11-28 20:00:00" + }, + "SC": { + "summer_peak_start": "2050-07-28 17:00:00", + "summer_peak_end": "2050-07-28 21:00:00", + "winter_peak_start": "2050-01-04 04:00:00", + "winter_peak_end": "2050-01-04 08:00:00", + "intermediate_peak_start": "2050-05-31 17:00:00", + "intermediate_peak_end": "2050-05-31 21:00:00" + }, + "MT": { + "summer_peak_start": "2050-08-06 16:00:00", + "summer_peak_end": "2050-08-06 20:00:00", + "winter_peak_start": "2050-01-18 17:00:00", + "winter_peak_end": "2050-01-18 21:00:00", + "intermediate_peak_start": "2050-10-06 19:00:00", + "intermediate_peak_end": "2050-10-06 23:00:00" + }, + "MS": { + "summer_peak_start": "2050-06-30 16:00:00", + "summer_peak_end": "2050-06-30 20:00:00", + "winter_peak_start": "2050-01-18 16:00:00", + "winter_peak_end": "2050-01-18 20:00:00", + "intermediate_peak_start": "2050-05-28 16:00:00", + "intermediate_peak_end": "2050-05-28 20:00:00" + }, + "NM": { + "summer_peak_start": "2050-08-09 17:00:00", + "summer_peak_end": "2050-08-09 21:00:00", + "winter_peak_start": "2050-03-11 16:00:00", + "winter_peak_end": "2050-03-11 20:00:00", + "intermediate_peak_start": "2050-10-31 17:00:00", + "intermediate_peak_end": "2050-10-31 21:00:00" + }, + "NJ": { + "summer_peak_start": "2050-07-06 16:00:00", + "summer_peak_end": "2050-07-06 20:00:00", + "winter_peak_start": "2050-12-07 16:00:00", + "winter_peak_end": "2050-12-07 20:00:00", + "intermediate_peak_start": "2050-05-31 17:00:00", + "intermediate_peak_end": "2050-05-31 21:00:00" + }, + "GA": { + "summer_peak_start": "2050-06-30 17:00:00", + "summer_peak_end": "2050-06-30 21:00:00", + "winter_peak_start": "2050-01-03 17:00:00", + "winter_peak_end": "2050-01-03 21:00:00", + "intermediate_peak_start": "2050-05-26 17:00:00", + "intermediate_peak_end": "2050-05-26 21:00:00" + }, + "CA": { + "summer_peak_start": "2050-08-14 16:00:00", + "summer_peak_end": "2050-08-14 20:00:00", + "winter_peak_start": "2050-12-14 16:00:00", + "winter_peak_end": "2050-12-14 20:00:00", + "intermediate_peak_start": "2050-10-02 16:00:00", + "intermediate_peak_end": "2050-10-02 20:00:00" + }, + "IL": { + "summer_peak_start": "2050-07-07 17:00:00", + "summer_peak_end": "2050-07-07 21:00:00", + "winter_peak_start": "2050-12-29 16:00:00", + "winter_peak_end": "2050-12-29 20:00:00", + "intermediate_peak_start": "2050-11-08 16:00:00", + "intermediate_peak_end": "2050-11-08 20:00:00" + }, + "AZ": { + "summer_peak_start": "2050-08-09 17:00:00", + "summer_peak_end": "2050-08-09 21:00:00", + "winter_peak_start": "2050-03-30 17:00:00", + "winter_peak_end": "2050-03-30 21:00:00", + "intermediate_peak_start": "2050-10-03 16:00:00", + "intermediate_peak_end": "2050-10-03 20:00:00" + }, + "TX": { + "summer_peak_start": "2050-08-31 16:00:00", + "summer_peak_end": "2050-08-31 20:00:00", + "winter_peak_start": "2050-12-27 15:00:00", + "winter_peak_end": "2050-12-27 19:00:00", + "intermediate_peak_start": "2050-10-03 16:00:00", + "intermediate_peak_end": "2050-10-03 20:00:00" + }, + "NH": { + "summer_peak_start": "2050-08-09 16:00:00", + "summer_peak_end": "2050-08-09 20:00:00", + "winter_peak_start": "2050-12-07 16:00:00", + "winter_peak_end": "2050-12-07 20:00:00", + "intermediate_peak_start": "2050-11-28 16:00:00", + "intermediate_peak_end": "2050-11-28 20:00:00" + }, + "DE": { + "summer_peak_start": "2050-06-30 16:00:00", + "summer_peak_end": "2050-06-30 20:00:00", + "winter_peak_start": "2050-12-07 16:00:00", + "winter_peak_end": "2050-12-07 20:00:00", + "intermediate_peak_start": "2050-11-27 16:00:00", + "intermediate_peak_end": "2050-11-27 20:00:00" + }, + "WA": { + "summer_peak_start": "2050-08-17 16:00:00", + "summer_peak_end": "2050-08-17 20:00:00", + "winter_peak_start": "2050-01-12 16:00:00", + "winter_peak_end": "2050-01-12 20:00:00", + "intermediate_peak_start": "2050-10-25 16:00:00", + "intermediate_peak_end": "2050-10-25 20:00:00" + }, + "OR": { + "summer_peak_start": "2050-09-19 16:00:00", + "summer_peak_end": "2050-09-19 20:00:00", + "winter_peak_start": "2050-12-14 16:00:00", + "winter_peak_end": "2050-12-14 20:00:00", + "intermediate_peak_start": "2050-10-26 16:00:00", + "intermediate_peak_end": "2050-10-26 20:00:00" + }, + "MI": { + "summer_peak_start": "2050-07-07 17:00:00", + "summer_peak_end": "2050-07-07 21:00:00", + "winter_peak_start": "2050-03-02 17:00:00", + "winter_peak_end": "2050-03-02 21:00:00", + "intermediate_peak_start": "2050-11-06 16:00:00", + "intermediate_peak_end": "2050-11-06 20:00:00" + }, + "MN": { + "summer_peak_start": "2050-08-03 17:00:00", + "summer_peak_end": "2050-08-03 21:00:00", + "winter_peak_start": "2050-12-12 17:00:00", + "winter_peak_end": "2050-12-12 21:00:00", + "intermediate_peak_start": "2050-04-12 16:00:00", + "intermediate_peak_end": "2050-04-12 20:00:00" + }, + "WY": { + "summer_peak_start": "2050-09-18 18:00:00", + "summer_peak_end": "2050-09-18 22:00:00", + "winter_peak_start": "2050-02-07 07:00:00", + "winter_peak_end": "2050-02-07 11:00:00", + "intermediate_peak_start": "2050-10-26 07:00:00", + "intermediate_peak_end": "2050-10-26 11:00:00" + }, + "IN": { + "summer_peak_start": "2050-07-07 17:00:00", + "summer_peak_end": "2050-07-07 21:00:00", + "winter_peak_start": "2050-12-28 17:00:00", + "winter_peak_end": "2050-12-28 21:00:00", + "intermediate_peak_start": "2050-11-28 16:00:00", + "intermediate_peak_end": "2050-11-28 20:00:00" + }, + "OK": { + "summer_peak_start": "2050-09-06 15:00:00", + "summer_peak_end": "2050-09-06 19:00:00", + "winter_peak_start": "2050-02-14 04:00:00", + "winter_peak_end": "2050-02-14 08:00:00", + "intermediate_peak_start": "2050-11-17 04:00:00", + "intermediate_peak_end": "2050-11-17 08:00:00" + }, + "NV": { + "summer_peak_start": "2050-07-12 16:00:00", + "summer_peak_end": "2050-07-12 20:00:00", + "winter_peak_start": "2050-12-29 16:00:00", + "winter_peak_end": "2050-12-29 20:00:00", + "intermediate_peak_start": "2050-05-17 17:00:00", + "intermediate_peak_end": "2050-05-17 21:00:00" + }, + "KS": { + "summer_peak_start": "2050-08-01 17:00:00", + "summer_peak_end": "2050-08-01 21:00:00", + "winter_peak_start": "2050-01-17 17:00:00", + "winter_peak_end": "2050-01-17 21:00:00", + "intermediate_peak_start": "2050-11-01 16:00:00", + "intermediate_peak_end": "2050-11-01 20:00:00" + }, + "PA": { + "summer_peak_start": "2050-07-18 16:00:00", + "summer_peak_end": "2050-07-18 20:00:00", + "winter_peak_start": "2050-01-03 16:00:00", + "winter_peak_end": "2050-01-03 20:00:00", + "intermediate_peak_start": "2050-05-29 16:00:00", + "intermediate_peak_end": "2050-05-29 20:00:00" + }, + "MO": { + "summer_peak_start": "2050-08-01 16:00:00", + "summer_peak_end": "2050-08-01 20:00:00", + "winter_peak_start": "2050-12-29 07:00:00", + "winter_peak_end": "2050-12-29 11:00:00", + "intermediate_peak_start": "2050-11-16 16:00:00", + "intermediate_peak_end": "2050-11-16 20:00:00" + }, + "ME": { + "summer_peak_start": "2050-08-10 16:00:00", + "summer_peak_end": "2050-08-10 20:00:00", + "winter_peak_start": "2050-02-15 16:00:00", + "winter_peak_end": "2050-02-15 20:00:00", + "intermediate_peak_start": "2050-11-28 16:00:00", + "intermediate_peak_end": "2050-11-28 20:00:00" + }, + "KY": { + "summer_peak_start": "2050-07-07 17:00:00", + "summer_peak_end": "2050-07-07 21:00:00", + "winter_peak_start": "2050-12-12 16:00:00", + "winter_peak_end": "2050-12-12 20:00:00", + "intermediate_peak_start": "2050-05-30 17:00:00", + "intermediate_peak_end": "2050-05-30 21:00:00" + }, + "CO": { + "summer_peak_start": "2050-08-09 16:00:00", + "summer_peak_end": "2050-08-09 20:00:00", + "winter_peak_start": "2050-12-26 17:00:00", + "winter_peak_end": "2050-12-26 21:00:00", + "intermediate_peak_start": "2050-11-27 16:00:00", + "intermediate_peak_end": "2050-11-27 20:00:00" + }, + "NC": { + "summer_peak_start": "2050-08-17 16:00:00", + "summer_peak_end": "2050-08-17 20:00:00", + "winter_peak_start": "2050-12-29 16:00:00", + "winter_peak_end": "2050-12-29 20:00:00", + "intermediate_peak_start": "2050-11-30 16:00:00", + "intermediate_peak_end": "2050-11-30 20:00:00" + }, + "AL": { + "summer_peak_start": "2050-06-30 16:00:00", + "summer_peak_end": "2050-06-30 20:00:00", + "winter_peak_start": "2050-01-03 17:00:00", + "winter_peak_end": "2050-01-03 21:00:00", + "intermediate_peak_start": "2050-05-26 16:00:00", + "intermediate_peak_end": "2050-05-26 20:00:00" + }, + "ND": { + "summer_peak_start": "2050-07-31 17:00:00", + "summer_peak_end": "2050-07-31 21:00:00", + "winter_peak_start": "2050-12-26 18:00:00", + "winter_peak_end": "2050-12-26 22:00:00", + "intermediate_peak_start": "2050-04-17 17:00:00", + "intermediate_peak_end": "2050-04-17 21:00:00" + }, + "AR": { + "summer_peak_start": "2050-08-08 16:00:00", + "summer_peak_end": "2050-08-08 20:00:00", + "winter_peak_start": "2050-12-12 16:00:00", + "winter_peak_end": "2050-12-12 20:00:00", + "intermediate_peak_start": "2050-05-30 16:00:00", + "intermediate_peak_end": "2050-05-30 20:00:00" + }, + "FL": { + "summer_peak_start": "2050-07-27 16:00:00", + "summer_peak_end": "2050-07-27 20:00:00", + "winter_peak_start": "2050-03-23 16:00:00", + "winter_peak_end": "2050-03-23 20:00:00", + "intermediate_peak_start": "2050-05-31 16:00:00", + "intermediate_peak_end": "2050-05-31 20:00:00" + }, + "ID": { + "summer_peak_start": "2050-08-10 17:00:00", + "summer_peak_end": "2050-08-10 21:00:00", + "winter_peak_start": "2050-01-12 17:00:00", + "winter_peak_end": "2050-01-12 21:00:00", + "intermediate_peak_start": "2050-11-15 17:00:00", + "intermediate_peak_end": "2050-11-15 21:00:00" + }, + "LA": { + "summer_peak_start": "2050-07-31 16:00:00", + "summer_peak_end": "2050-07-31 20:00:00", + "winter_peak_start": "2050-12-12 16:00:00", + "winter_peak_end": "2050-12-12 20:00:00", + "intermediate_peak_start": "2050-05-30 16:00:00", + "intermediate_peak_end": "2050-05-30 20:00:00" + }, + "MD": { + "summer_peak_start": "2050-07-06 16:00:00", + "summer_peak_end": "2050-07-06 20:00:00", + "winter_peak_start": "2050-01-09 16:00:00", + "winter_peak_end": "2050-01-09 20:00:00", + "intermediate_peak_start": "2050-05-26 16:00:00", + "intermediate_peak_end": "2050-05-26 20:00:00" + }, + "NE": { + "summer_peak_start": "2050-07-15 15:00:00", + "summer_peak_end": "2050-07-15 19:00:00", + "winter_peak_start": "2050-03-16 15:00:00", + "winter_peak_end": "2050-03-16 19:00:00", + "intermediate_peak_start": "2050-10-31 15:00:00", + "intermediate_peak_end": "2050-10-31 19:00:00" + }, + "RI": { + "summer_peak_start": "2050-07-19 17:00:00", + "summer_peak_end": "2050-07-19 21:00:00", + "winter_peak_start": "2050-12-07 16:00:00", + "winter_peak_end": "2050-12-07 20:00:00", + "intermediate_peak_start": "2050-10-18 17:00:00", + "intermediate_peak_end": "2050-10-18 21:00:00" + } +} \ No newline at end of file diff --git a/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/setpoint_modifier.rb b/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/setpoint_modifier.rb index fe83e90dfc..9d52e46d10 100644 --- a/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/setpoint_modifier.rb +++ b/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/setpoint_modifier.rb @@ -8,12 +8,12 @@ require resource_file end -FlexibilityInputs = Struct.new(:peak_duration_steps, :peak_offset, :pre_peak_duration_steps, :pre_peak_offset, :random_shift_steps, keyword_init: true) +FlexibilityInputs = Struct.new(:peak_offset, :pre_peak_duration_steps, :pre_peak_offset, :random_shift_steps, keyword_init: true) DailyPeakIndices = Struct.new(:pre_peak_start_index, :peak_start_index, :peak_end_index) - +DSTInfo = Struct.new(:dst_begin_month, :dst_begin_day, :dst_end_month, :dst_end_day) class HVACScheduleModifier - def initialize(state:, sim_year:, weather:, epw_path:, minutes_per_step:, runner:) + def initialize(state:, sim_year:, weather:, epw_path:, minutes_per_step:, runner:, dst_info:) @state = state @minutes_per_step = minutes_per_step @runner = runner @@ -26,8 +26,9 @@ def initialize(state:, sim_year:, weather:, epw_path:, minutes_per_step:, runner @steps_in_day = 24 * 60 / @minutes_per_step @num_timesteps_per_hour = 60 / @minutes_per_step current_dir = File.dirname(__FILE__) - @summer_peak_hours_dict = JSON.parse(File.read("#{current_dir}/state_summer_peak_hour_dict.json")) - @winter_peak_hours_dict = JSON.parse(File.read("#{current_dir}/state_winter_peak_hour_dict.json")) + @peak_hours_dict_shift = JSON.parse(File.read("#{current_dir}/seasonal_shifting_peak_hours.json")) + @peak_hours_dict_shed = JSON.parse(File.read("#{current_dir}/seasonal_shedding_peak_hours.json")) + @dst_info = dst_info end def modify_setpoints(setpoints, flexibility_inputs) @@ -40,78 +41,104 @@ def modify_setpoints(setpoints, flexibility_inputs) total_indices.times do |index| offset_times = _get_peak_times(index, flexibility_inputs) day_type = _get_day_type(index) - if day_type == 'heating' - heating_setpoint[index] += _get_setpoint_offset(index, 'heating', offset_times, flexibility_inputs) - # If the offset causes the set points to be inverted, adjust the cooling setpoint to correct it - # This can happen during pre-heating if originally the cooling and heating setpoints were the same - if heating_setpoint[index] > cooling_setpoint[index] - cooling_setpoint[index] = heating_setpoint[index] - end - else - cooling_setpoint[index] += _get_setpoint_offset(index, 'cooling', offset_times, flexibility_inputs) - # If the offset causes the set points to be inverted, adjust the heating setpoint to correct it - # This can happen during pre-cooling if originally the cooling and heating setpoints were the same - if heating_setpoint[index] > cooling_setpoint[index] - heating_setpoint[index] = cooling_setpoint[index] + index_in_day = index % (24 * @num_timesteps_per_hour) + if offset_times.pre_peak_start_index <= index_in_day && index_in_day < offset_times.peak_start_index + # Preheating + if day_type == 'preheating' + heating_setpoint[index] += flexibility_inputs.pre_peak_offset + heating_setpoint[index] = _clip_setpoints(heating_setpoint[index]) + # If the offset causes the set points to be inverted, adjust the cooling setpoint to correct it + # This can happen during pre-heating if originally the cooling and heating setpoints were the same + if heating_setpoint[index] > cooling_setpoint[index] + cooling_setpoint[index] = heating_setpoint[index] + end + elsif day_type == 'precooling' + cooling_setpoint[index] -= flexibility_inputs.pre_peak_offset + cooling_setpoint[index] = _clip_setpoints(cooling_setpoint[index]) + # If the offset causes the set points to be inverted, adjust the heating setpoint to correct it + # This can happen during precooling if originally the cooling and heating setpoints were the same + if heating_setpoint[index] > cooling_setpoint[index] + heating_setpoint[index] = cooling_setpoint[index] + end end + elsif offset_times.peak_start_index <= index_in_day && index_in_day < offset_times.peak_end_index + # Peak + heating_setpoint[index] -= flexibility_inputs.peak_offset + cooling_setpoint[index] += flexibility_inputs.peak_offset end end { heating_setpoint: heating_setpoint, cooling_setpoint: cooling_setpoint } end - def _get_peak_times(index, flexibility_inputs) - month = _get_month(index:) - peak_hour = _get_peak_hour(month:) - peak_index = peak_hour * @num_timesteps_per_hour - peak_times = DailyPeakIndices.new - peak_times.peak_start_index = peak_index + flexibility_inputs.random_shift_steps - peak_times.peak_end_index = peak_times.peak_start_index + flexibility_inputs.peak_duration_steps - peak_times.pre_peak_start_index = peak_times.peak_start_index - flexibility_inputs.pre_peak_duration_steps - peak_times + def _clip_setpoints(setpoint) + return 82 if setpoint > 82 + return 55 if setpoint < 55 + setpoint end - def _get_setpoint_offset(index, setpoint_type, offset_times, flexibility_inputs) - case setpoint_type - when 'heating' - pre_peak_offset = flexibility_inputs.pre_peak_offset - peak_offset = -flexibility_inputs.peak_offset - when 'cooling' - pre_peak_offset = -flexibility_inputs.pre_peak_offset - peak_offset = flexibility_inputs.peak_offset - else - raise "Unsupported setpoint type: #{setpoint_type}" - end + def _get_peak_times(index, flexibility_inputs) + month, day = _get_month_day(index:) - index_in_day = index % (24 * @num_timesteps_per_hour) - if offset_times.pre_peak_start_index <= index_in_day && index_in_day < offset_times.peak_start_index - pre_peak_offset - elsif offset_times.peak_start_index <= index_in_day && index_in_day < offset_times.peak_end_index - peak_offset - else - 0 + pre_peak_duration = flexibility_inputs.pre_peak_duration_steps + peak_hour_start, peak_hour_end = _get_peak_hour(pre_peak_duration, month:) + if @dst_info.values.all? { |v| !v.nil? } + dst_adjust_hour = _dst_ajustment(month, day) + peak_hour_start += dst_adjust_hour + peak_hour_end += dst_adjust_hour end + + peak_times = DailyPeakIndices.new + random_shift_steps = flexibility_inputs.random_shift_steps + peak_times.peak_start_index = peak_hour_start * @num_timesteps_per_hour + random_shift_steps + peak_times.peak_end_index = peak_hour_end * @num_timesteps_per_hour + random_shift_steps + peak_times.pre_peak_start_index = peak_times.peak_start_index - flexibility_inputs.pre_peak_duration_steps + return peak_times end - def _get_month(index:) + def _get_month_day(index:) start_of_year = Date.new(@sim_year, 1, 1) index_date = start_of_year + (index.to_f / @num_timesteps_per_hour / 24) index_date.month + index_date.day + return index_date.month, index_date.day end - def _get_peak_hour(month:) + def _get_peak_hour(pre_peak_duration, month:) + if pre_peak_duration == 0 + peak_hours = @peak_hours_dict_shed[@state] + else + peak_hours = @peak_hours_dict_shift[@state] + end if [6, 7, 8, 9].include?(month) - return @summer_peak_hours_dict[@state] + return peak_hours["summer_peak_start"][11..12].to_i, peak_hours["summer_peak_end"][11..12].to_i + elsif [1, 2, 3, 12].include?(month) + return peak_hours["winter_peak_start"][11..12].to_i, peak_hours["winter_peak_end"][11..12].to_i + else + return peak_hours["intermediate_peak_start"][11..12].to_i, peak_hours["intermediate_peak_end"][11..12].to_i + end + end + + def _dst_ajustment(month, day) + if month > @dst_info.dst_begin_month && month < @dst_info.dst_end_month + dst_adjust_hour = 1 + elsif month == @dst_info.dst_begin_month && day >= @dst_info.dst_begin_day # double check + dst_adjust_hour = 1 + elsif month == @dst_info.dst_end_month && day < @dst_info.dst_end_day # double check + dst_adjust_hour = 1 else - return @winter_peak_hours_dict[@state] + dst_adjust_hour = 0 end + return dst_adjust_hour end def _get_day_type(index) day = index / @steps_in_day - if @daily_avg_temps[day] < 66.0 - return 'heating' + if @daily_avg_temps[day] < 50.0 + return 'preheating' + elsif @daily_avg_temps[day] > 68.0 + return 'precooling' else - return 'cooling' + return 'prenothing' # Neither preheating nor precooling end end @@ -137,7 +164,6 @@ def _get_daily_avg_temps def log_inputs(inputs) return unless @runner @runner.registerInfo("Modifying setpoints ...") - @runner.registerInfo("peak_duration_steps=#{inputs.peak_duration_steps}") @runner.registerInfo("pre_peak_duration_steps=#{inputs.pre_peak_duration_steps}") @runner.registerInfo("random_shift_steps=#{inputs.random_shift_steps}") @runner.registerInfo("pre_peak_offset=#{inputs.pre_peak_offset}") diff --git a/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/state_summer_peak_hour_dict.json b/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/state_summer_peak_hour_dict.json deleted file mode 100644 index 77be8695cc..0000000000 --- a/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/state_summer_peak_hour_dict.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "IA": 18, - "WV": 18, - "MA": 18, - "VT": 19, - "WI": 19, - "CT": 18, - "TN": 18, - "NY": 19, - "UT": 19, - "VA": 19, - "SD": 21, - "OH": 19, - "SC": 19, - "MT": 18, - "MS": 18, - "NM": 19, - "NJ": 18, - "GA": 19, - "CA": 18, - "IL": 19, - "AZ": 19, - "TX": 18, - "NH": 18, - "DE": 18, - "WA": 18, - "OR": 18, - "MI": 19, - "MN": 19, - "WY": 20, - "IN": 19, - "OK": 17, - "NV": 18, - "KS": 19, - "PA": 18, - "MO": 18, - "ME": 18, - "KY": 19, - "CO": 18, - "NC": 18, - "AL": 18, - "ND": 19, - "AR": 18, - "FL": 18, - "ID": 19, - "LA": 18, - "MD": 18, - "NE": 17, - "RI": 19 -} \ No newline at end of file diff --git a/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/state_winter_peak_hour_dict.json b/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/state_winter_peak_hour_dict.json deleted file mode 100644 index f96988a3ae..0000000000 --- a/measures/ResStockArgumentsPostHPXML/resources/hvac_flexibility/state_winter_peak_hour_dict.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "IA": 18, - "WV": 18, - "MA": 18, - "VT": 18, - "WI": 18, - "CT": 19, - "TN": 18, - "NY": 19, - "UT": 18, - "VA": 18, - "SD": 18, - "OH": 18, - "SC": 6, - "MT": 19, - "MS": 18, - "NM": 19, - "NJ": 18, - "GA": 19, - "CA": 18, - "IL": 18, - "AZ": 18, - "TX": 18, - "NH": 18, - "DE": 18, - "WA": 18, - "OR": 18, - "MI": 19, - "MN": 19, - "WY": 9, - "IN": 19, - "OK": 6, - "NV": 19, - "KS": 19, - "PA": 18, - "MO": 18, - "ME": 18, - "KY": 18, - "CO": 19, - "NC": 18, - "AL": 18, - "ND": 20, - "AR": 18, - "FL": 18, - "ID": 19, - "LA": 18, - "MD": 18, - "NE": 17, - "RI": 18 -} \ No newline at end of file diff --git a/measures/ResStockArgumentsPostHPXML/tests/baseline.osw b/measures/ResStockArgumentsPostHPXML/tests/baseline.osw new file mode 100644 index 0000000000..3f8488d0f6 --- /dev/null +++ b/measures/ResStockArgumentsPostHPXML/tests/baseline.osw @@ -0,0 +1,332 @@ +{ + "measure_paths": [ + "../../../measures", + "../../../resources/hpxml-measures" + ], + "steps": [ + { + "arguments": { + "apply_defaults": true, + "site_state_code" : "CO", + "simulation_control_daylight_saving_enabled": false, + "air_leakage_house_pressure": 50, + "site_shielding_of_home": "normal", + "air_leakage_units": "ACH", + "air_leakage_value": 3, + "bathroom_fans_quantity": 0, + "ceiling_assembly_r": 39.3, + "ceiling_fan_cooling_setpoint_temp_offset": 0, + "ceiling_fan_present": false, + "clothes_dryer_present": true, + "clothes_dryer_efficiency": 3.73, + "clothes_dryer_efficiency_type": "CombinedEnergyFactor", + "clothes_dryer_fuel_type": "electricity", + "clothes_dryer_location": "conditioned space", + "clothes_dryer_usage_multiplier": 1.0, + "clothes_dryer_vented_flow_rate": 150.0, + "clothes_washer_present": true, + "clothes_washer_capacity": 3.2, + "clothes_washer_efficiency": 1.21, + "clothes_washer_efficiency_type": "IntegratedModifiedEnergyFactor", + "clothes_washer_label_annual_gas_cost": 27.0, + "clothes_washer_label_electric_rate": 0.12, + "clothes_washer_label_gas_rate": 1.09, + "clothes_washer_label_usage": 6.0, + "clothes_washer_location": "conditioned space", + "clothes_washer_rated_annual_kwh": 380.0, + "clothes_washer_usage_multiplier": 1.0, + "cooking_range_oven_present": true, + "cooking_range_oven_fuel_type": "electricity", + "cooking_range_oven_is_convection": false, + "cooking_range_oven_is_induction": false, + "cooking_range_oven_location": "conditioned space", + "cooking_range_oven_usage_multiplier": 1.0, + "cooling_system_cooling_capacity": 48000.0, + "cooling_system_cooling_compressor_type": "single stage", + "cooling_system_cooling_efficiency_type": "SEER", + "cooling_system_cooling_efficiency": 13.0, + "cooling_system_cooling_sensible_heat_fraction": 0.73, + "cooling_system_fraction_cool_load_served": 1, + "cooling_system_is_ducted": false, + "cooling_system_type": "none", + "dehumidifier_capacity": 40, + "dehumidifier_efficiency": 1.8, + "dehumidifier_efficiency_type": "EnergyFactor", + "dehumidifier_fraction_dehumidification_load_served": 1, + "dehumidifier_rh_setpoint": 0.5, + "dehumidifier_type": "none", + "hot_water_distribution_pipe_r": 0.0, + "hot_water_distribution_recirc_branch_piping_length": 50, + "hot_water_distribution_recirc_control_type": "no control", + "hot_water_distribution_recirc_piping_length": 50, + "hot_water_distribution_recirc_pump_power": 50, + "hot_water_distribution_standard_piping_length": 50, + "hot_water_distribution_system_type": "Standard", + "dishwasher_present": true, + "dishwasher_efficiency": 307, + "dishwasher_efficiency_type": "RatedAnnualkWh", + "dishwasher_label_annual_gas_cost": 22.32, + "dishwasher_label_electric_rate": 0.12, + "dishwasher_label_gas_rate": 1.09, + "dishwasher_label_usage": 4.0, + "dishwasher_location": "conditioned space", + "dishwasher_place_setting_capacity": 12, + "dishwasher_usage_multiplier": 1.0, + "door_area": 30.0, + "door_rvalue": 4.4, + "ducts_return_insulation_r": 0.0, + "ducts_leakage_units": "CFM25", + "ducts_return_leakage_to_outside_value": 25.0, + "ducts_supply_insulation_r": 4.0, + "ducts_supply_leakage_to_outside_value": 75.0, + "dwhr_efficiency": 0.55, + "dwhr_equal_flow": true, + "dwhr_facilities_connected": "none", + "extra_refrigerator_present": false, + "extra_refrigerator_usage_multiplier": 1.0, + "floor_type": "WoodFrame", + "floor_over_foundation_assembly_r": 18.7, + "floor_over_garage_assembly_r": 18.7, + "foundation_wall_insulation_distance_to_bottom": 8.0, + "foundation_wall_insulation_distance_to_top": 0.0, + "foundation_wall_insulation_r": 8.9, + "foundation_wall_thickness": 8.0, + "foundation_wall_type": "solid concrete", + "freezer_present": false, + "freezer_usage_multiplier": 1.0, + "misc_fuel_loads_fireplace_fuel_type": "natural gas", + "misc_fuel_loads_fireplace_present": false, + "misc_fuel_loads_fireplace_usage_multiplier": 0.0, + "misc_fuel_loads_grill_fuel_type": "natural gas", + "misc_fuel_loads_grill_present": false, + "misc_fuel_loads_grill_usage_multiplier": 0.0, + "misc_fuel_loads_lighting_fuel_type": "natural gas", + "misc_fuel_loads_lighting_present": false, + "misc_fuel_loads_lighting_usage_multiplier": 0.0, + "geometry_unit_aspect_ratio": 1.8, + "geometry_attic_type": "UnventedAttic", + "geometry_unit_cfa": 4500.0, + "geometry_eaves_depth": 3, + "geometry_foundation_height": 8.0, + "geometry_foundation_height_above_grade": 0.0, + "geometry_foundation_type": "ConditionedBasement", + "geometry_garage_depth": 24.0, + "geometry_garage_position": "Right", + "geometry_garage_protrusion": 0.5, + "geometry_garage_width": 12.0, + "geometry_unit_num_bathrooms": 3, + "geometry_unit_num_bedrooms": 4, + "geometry_unit_num_floors_above_grade": 1, + "geometry_unit_num_occupants": 3, + "geometry_unit_orientation": 180.0, + "geometry_rim_joist_height": 9.25, + "geometry_roof_pitch": "6:12", + "geometry_roof_type": "gable", + "geometry_unit_type": "single-family detached", + "geometry_average_ceiling_height": 8.0, + "geometry_unit_left_wall_is_adiabatic": false, + "geometry_unit_right_wall_is_adiabatic": false, + "geometry_unit_front_wall_is_adiabatic": false, + "geometry_unit_back_wall_is_adiabatic": false, + "heat_pump_backup_fuel": "electricity", + "heat_pump_backup_type": "integrated", + "heat_pump_backup_heating_capacity": 100000.0, + "heat_pump_backup_heating_efficiency": 1, + "heat_pump_heating_capacity_retention_fraction": 0.25, + "heat_pump_heating_capacity_retention_temp": -5, + "heat_pump_cooling_capacity": 60000.0, + "heat_pump_cooling_compressor_type": "variable speed", + "heat_pump_cooling_efficiency_type": "SEER", + "heat_pump_cooling_efficiency": 13.0, + "heat_pump_cooling_sensible_heat_fraction": 0.73, + "heat_pump_fraction_cool_load_served": 1, + "heat_pump_fraction_heat_load_served": 1, + "heat_pump_heating_capacity": 60000.0, + "heat_pump_heating_efficiency_type": "HSPF", + "heat_pump_heating_efficiency": 7.7, + "heat_pump_type": "mini-split", + "heating_system_fraction_heat_load_served": 1, + "heating_system_2_fraction_heat_load_served": 0.25, + "heating_system_fuel": "natural gas", + "heating_system_2_fuel": "electricity", + "heating_system_heating_capacity": 64000.0, + "heating_system_heating_efficiency": 0.92, + "heating_system_2_heating_efficiency": 1.0, + "heating_system_type": "none", + "heating_system_2_type": "none", + "holiday_lighting_present": false, + "permanent_spa_heater_type": "electric resistance", + "permanent_spa_heater_usage_multiplier": 1.0, + "permanent_spa_present": false, + "permanent_spa_pump_usage_multiplier": 1.0, + "hpxml_path": "measures/ResStockArgumentsPostHPXML/tests/baseline.xml", + "kitchen_fans_quantity": 0, + "lighting_present": true, + "lighting_exterior_fraction_cfl": 0.4, + "lighting_garage_fraction_cfl": 0.4, + "lighting_interior_fraction_cfl": 0.4, + "lighting_exterior_fraction_led": 0.25, + "lighting_garage_fraction_led": 0.25, + "lighting_interior_fraction_led": 0.25, + "lighting_exterior_fraction_lfl": 0.1, + "lighting_garage_fraction_lfl": 0.1, + "lighting_interior_fraction_lfl": 0.1, + "lighting_exterior_usage_multiplier": 1.0, + "lighting_garage_usage_multiplier": 1.0, + "lighting_interior_usage_multiplier": 1.0, + "mech_vent_fan_power": 30, + "mech_vent_2_fan_power": 30, + "mech_vent_fan_type": "none", + "mech_vent_2_fan_type": "none", + "mech_vent_flow_rate": 110, + "mech_vent_2_flow_rate": 110, + "mech_vent_hours_in_operation": 24, + "mech_vent_2_hours_in_operation": 24, + "mech_vent_num_units_served": 1, + "mech_vent_sensible_recovery_efficiency": 0.72, + "mech_vent_2_sensible_recovery_efficiency": 0.72, + "mech_vent_recovery_efficiency_type": "Unadjusted", + "mech_vent_2_recovery_efficiency_type": "Unadjusted", + "mech_vent_total_recovery_efficiency": 0.48, + "mech_vent_2_total_recovery_efficiency": 0.48, + "neighbor_back_distance": 0, + "neighbor_front_distance": 0, + "neighbor_left_distance": 10, + "neighbor_right_distance": 10, + "overhangs_back_depth": 2, + "overhangs_back_distance_to_top_of_window": 0, + "overhangs_back_distance_to_bottom_of_window": 4, + "overhangs_front_depth": 2, + "overhangs_front_distance_to_top_of_window": 0, + "overhangs_front_distance_to_bottom_of_window": 4, + "overhangs_left_depth": 2, + "overhangs_left_distance_to_top_of_window": 0, + "overhangs_left_distance_to_bottom_of_window": 4, + "overhangs_right_depth": 2, + "overhangs_right_distance_to_top_of_window": 0, + "overhangs_right_distance_to_bottom_of_window": 4, + "misc_plug_loads_other_annual_kwh": 2457.0, + "misc_plug_loads_other_frac_latent": 0.045, + "misc_plug_loads_other_frac_sensible": 0.855, + "misc_plug_loads_other_usage_multiplier": 1.0, + "misc_plug_loads_television_present": true, + "misc_plug_loads_television_annual_kwh": 620.0, + "misc_plug_loads_television_usage_multiplier": 1.0, + "misc_plug_loads_vehicle_present": false, + "misc_plug_loads_vehicle_usage_multiplier": 0.0, + "misc_plug_loads_well_pump_present": false, + "misc_plug_loads_well_pump_usage_multiplier": 0.0, + "pool_heater_type": "electric resistance", + "pool_heater_usage_multiplier": 1.0, + "pool_present": false, + "pool_pump_usage_multiplier": 1.0, + "pv_system_present": false, + "pv_system_2_present": false, + "pv_system_array_azimuth": 180, + "pv_system_2_array_azimuth": 180, + "pv_system_array_tilt": 20, + "pv_system_2_array_tilt": 20, + "pv_system_inverter_efficiency": 0.96, + "pv_system_max_power_output": 4000, + "pv_system_2_max_power_output": 4000, + "pv_system_num_bedrooms_served": 3, + "pv_system_system_losses_fraction": 0.14, + "battery_present": false, + "refrigerator_present": true, + "refrigerator_location": "conditioned space", + "refrigerator_rated_annual_kwh": 650.0, + "refrigerator_usage_multiplier": 1.0, + "rim_joist_assembly_r": 23.0, + "roof_assembly_r": 2.3, + "roof_color": "medium", + "roof_material_type": "asphalt or fiberglass shingles", + "radiant_barrier_attic_location": "none", + "radiant_barrier_grade": "1", + "hvac_control_cooling_weekday_setpoint": "78", + "hvac_control_cooling_weekend_setpoint": "78", + "hvac_control_heating_weekday_setpoint": "68", + "hvac_control_heating_weekend_setpoint": "68", + "simulation_control_timestep": 60, + "site_type": "suburban", + "skylight_area_back": 0, + "skylight_area_front": 0, + "skylight_area_left": 0, + "skylight_area_right": 0, + "skylight_shgc": 0.45, + "skylight_ufactor": 0.33, + "slab_carpet_fraction": 0.0, + "slab_carpet_r": 0.0, + "slab_perimeter_insulation_depth": 0, + "slab_perimeter_insulation_r": 0, + "slab_thickness": 4.0, + "slab_under_insulation_r": 0, + "slab_under_insulation_width": 0, + "solar_thermal_collector_area": 40.0, + "solar_thermal_collector_azimuth": 180, + "solar_thermal_collector_loop_type": "liquid direct", + "solar_thermal_collector_rated_optical_efficiency": 0.5, + "solar_thermal_collector_rated_thermal_losses": 0.2799, + "solar_thermal_collector_tilt": 20, + "solar_thermal_collector_type": "evacuated tube", + "solar_thermal_solar_fraction": 0, + "solar_thermal_system_type": "none", + "wall_assembly_r": 23, + "wall_color": "medium", + "wall_siding_type": "wood siding", + "wall_type": "WoodStud", + "water_fixtures_shower_low_flow": true, + "water_fixtures_sink_low_flow": false, + "water_fixtures_usage_multiplier": 1.0, + "water_heater_efficiency": 0.95, + "water_heater_efficiency_type": "EnergyFactor", + "water_heater_fuel_type": "electricity", + "water_heater_jacket_rvalue": 0, + "water_heater_location": "conditioned space", + "water_heater_recovery_efficiency": 0.76, + "water_heater_setpoint_temperature": 125, + "water_heater_standby_loss": 0, + "water_heater_tank_volume": 40, + "water_heater_type": "instantaneous water heater", + "weather_station_epw_filepath": "USA_CO_Denver.Intl.AP.725650_TMY3.epw", + "whole_house_fan_flow_rate": 4500, + "whole_house_fan_power": 300, + "whole_house_fan_present": false, + "window_area_back": 0.0, + "window_area_front": 0.0, + "window_area_left": 0.0, + "window_area_right": 0.0, + "window_aspect_ratio": 1.333, + "window_back_wwr": 0.12, + "window_fraction_operable": 0.67, + "window_front_wwr": 0.12, + "window_interior_shading_summer": 0.7, + "window_interior_shading_winter": 0.85, + "window_left_wwr": 0.12, + "window_right_wwr": 0.12, + "window_shgc": 0.45, + "window_ufactor": 0.33 + }, + "measure_dir_name": "BuildResidentialHPXML" + }, + { + "measure_dir_name": "ResStockArgumentsPostHPXML", + "arguments": { + "hpxml_path": "tests/baseline.xml", + "loadflex_peak_offset": 0, + "loadflex_pre_peak_duration_hours": 0, + "loadflex_pre_peak_offset": 0, + "loadflex_random_shift_minutes": 0, + "output_csv_path": "tests", + "building_id": 1 + } + }, + { + "arguments": { + "hpxml_path": "measures/ResStockArgumentsPostHPXML/tests/baseline.xml", + "output_dir": "measures/ResStockArgumentsPostHPXML/tests", + "debug": "true" + }, + "measure_dir_name": "HPXMLtoOpenStudio" + } + ] +} \ No newline at end of file diff --git a/measures/ResStockArgumentsPostHPXML/tests/baseline_dst_impacted.osw b/measures/ResStockArgumentsPostHPXML/tests/baseline_dst_impacted.osw new file mode 100644 index 0000000000..6e1b6e0016 --- /dev/null +++ b/measures/ResStockArgumentsPostHPXML/tests/baseline_dst_impacted.osw @@ -0,0 +1,332 @@ +{ + "measure_paths": [ + "../../../measures", + "../../../resources/hpxml-measures" + ], + "steps": [ + { + "arguments": { + "apply_defaults": true, + "site_state_code" : "CO", + "simulation_control_daylight_saving_enabled": true, + "air_leakage_house_pressure": 50, + "site_shielding_of_home": "normal", + "air_leakage_units": "ACH", + "air_leakage_value": 3, + "bathroom_fans_quantity": 0, + "ceiling_assembly_r": 39.3, + "ceiling_fan_cooling_setpoint_temp_offset": 0, + "ceiling_fan_present": false, + "clothes_dryer_present": true, + "clothes_dryer_efficiency": 3.73, + "clothes_dryer_efficiency_type": "CombinedEnergyFactor", + "clothes_dryer_fuel_type": "electricity", + "clothes_dryer_location": "conditioned space", + "clothes_dryer_usage_multiplier": 1.0, + "clothes_dryer_vented_flow_rate": 150.0, + "clothes_washer_present": true, + "clothes_washer_capacity": 3.2, + "clothes_washer_efficiency": 1.21, + "clothes_washer_efficiency_type": "IntegratedModifiedEnergyFactor", + "clothes_washer_label_annual_gas_cost": 27.0, + "clothes_washer_label_electric_rate": 0.12, + "clothes_washer_label_gas_rate": 1.09, + "clothes_washer_label_usage": 6.0, + "clothes_washer_location": "conditioned space", + "clothes_washer_rated_annual_kwh": 380.0, + "clothes_washer_usage_multiplier": 1.0, + "cooking_range_oven_present": true, + "cooking_range_oven_fuel_type": "electricity", + "cooking_range_oven_is_convection": false, + "cooking_range_oven_is_induction": false, + "cooking_range_oven_location": "conditioned space", + "cooking_range_oven_usage_multiplier": 1.0, + "cooling_system_cooling_capacity": 48000.0, + "cooling_system_cooling_compressor_type": "single stage", + "cooling_system_cooling_efficiency_type": "SEER", + "cooling_system_cooling_efficiency": 13.0, + "cooling_system_cooling_sensible_heat_fraction": 0.73, + "cooling_system_fraction_cool_load_served": 1, + "cooling_system_is_ducted": false, + "cooling_system_type": "none", + "dehumidifier_capacity": 40, + "dehumidifier_efficiency": 1.8, + "dehumidifier_efficiency_type": "EnergyFactor", + "dehumidifier_fraction_dehumidification_load_served": 1, + "dehumidifier_rh_setpoint": 0.5, + "dehumidifier_type": "none", + "hot_water_distribution_pipe_r": 0.0, + "hot_water_distribution_recirc_branch_piping_length": 50, + "hot_water_distribution_recirc_control_type": "no control", + "hot_water_distribution_recirc_piping_length": 50, + "hot_water_distribution_recirc_pump_power": 50, + "hot_water_distribution_standard_piping_length": 50, + "hot_water_distribution_system_type": "Standard", + "dishwasher_present": true, + "dishwasher_efficiency": 307, + "dishwasher_efficiency_type": "RatedAnnualkWh", + "dishwasher_label_annual_gas_cost": 22.32, + "dishwasher_label_electric_rate": 0.12, + "dishwasher_label_gas_rate": 1.09, + "dishwasher_label_usage": 4.0, + "dishwasher_location": "conditioned space", + "dishwasher_place_setting_capacity": 12, + "dishwasher_usage_multiplier": 1.0, + "door_area": 30.0, + "door_rvalue": 4.4, + "ducts_return_insulation_r": 0.0, + "ducts_leakage_units": "CFM25", + "ducts_return_leakage_to_outside_value": 25.0, + "ducts_supply_insulation_r": 4.0, + "ducts_supply_leakage_to_outside_value": 75.0, + "dwhr_efficiency": 0.55, + "dwhr_equal_flow": true, + "dwhr_facilities_connected": "none", + "extra_refrigerator_present": false, + "extra_refrigerator_usage_multiplier": 1.0, + "floor_type": "WoodFrame", + "floor_over_foundation_assembly_r": 18.7, + "floor_over_garage_assembly_r": 18.7, + "foundation_wall_insulation_distance_to_bottom": 8.0, + "foundation_wall_insulation_distance_to_top": 0.0, + "foundation_wall_insulation_r": 8.9, + "foundation_wall_thickness": 8.0, + "foundation_wall_type": "solid concrete", + "freezer_present": false, + "freezer_usage_multiplier": 1.0, + "misc_fuel_loads_fireplace_fuel_type": "natural gas", + "misc_fuel_loads_fireplace_present": false, + "misc_fuel_loads_fireplace_usage_multiplier": 0.0, + "misc_fuel_loads_grill_fuel_type": "natural gas", + "misc_fuel_loads_grill_present": false, + "misc_fuel_loads_grill_usage_multiplier": 0.0, + "misc_fuel_loads_lighting_fuel_type": "natural gas", + "misc_fuel_loads_lighting_present": false, + "misc_fuel_loads_lighting_usage_multiplier": 0.0, + "geometry_unit_aspect_ratio": 1.8, + "geometry_attic_type": "UnventedAttic", + "geometry_unit_cfa": 4500.0, + "geometry_eaves_depth": 3, + "geometry_foundation_height": 8.0, + "geometry_foundation_height_above_grade": 0.0, + "geometry_foundation_type": "ConditionedBasement", + "geometry_garage_depth": 24.0, + "geometry_garage_position": "Right", + "geometry_garage_protrusion": 0.5, + "geometry_garage_width": 12.0, + "geometry_unit_num_bathrooms": 3, + "geometry_unit_num_bedrooms": 4, + "geometry_unit_num_floors_above_grade": 1, + "geometry_unit_num_occupants": 3, + "geometry_unit_orientation": 180.0, + "geometry_rim_joist_height": 9.25, + "geometry_roof_pitch": "6:12", + "geometry_roof_type": "gable", + "geometry_unit_type": "single-family detached", + "geometry_average_ceiling_height": 8.0, + "geometry_unit_left_wall_is_adiabatic": false, + "geometry_unit_right_wall_is_adiabatic": false, + "geometry_unit_front_wall_is_adiabatic": false, + "geometry_unit_back_wall_is_adiabatic": false, + "heat_pump_backup_fuel": "electricity", + "heat_pump_backup_type": "integrated", + "heat_pump_backup_heating_capacity": 100000.0, + "heat_pump_backup_heating_efficiency": 1, + "heat_pump_heating_capacity_retention_fraction": 0.25, + "heat_pump_heating_capacity_retention_temp": -5, + "heat_pump_cooling_capacity": 60000.0, + "heat_pump_cooling_compressor_type": "variable speed", + "heat_pump_cooling_efficiency_type": "SEER", + "heat_pump_cooling_efficiency": 13.0, + "heat_pump_cooling_sensible_heat_fraction": 0.73, + "heat_pump_fraction_cool_load_served": 1, + "heat_pump_fraction_heat_load_served": 1, + "heat_pump_heating_capacity": 60000.0, + "heat_pump_heating_efficiency_type": "HSPF", + "heat_pump_heating_efficiency": 7.7, + "heat_pump_type": "mini-split", + "heating_system_fraction_heat_load_served": 1, + "heating_system_2_fraction_heat_load_served": 0.25, + "heating_system_fuel": "natural gas", + "heating_system_2_fuel": "electricity", + "heating_system_heating_capacity": 64000.0, + "heating_system_heating_efficiency": 0.92, + "heating_system_2_heating_efficiency": 1.0, + "heating_system_type": "none", + "heating_system_2_type": "none", + "holiday_lighting_present": false, + "permanent_spa_heater_type": "electric resistance", + "permanent_spa_heater_usage_multiplier": 1.0, + "permanent_spa_present": false, + "permanent_spa_pump_usage_multiplier": 1.0, + "hpxml_path": "measures/ResStockArgumentsPostHPXML/tests/baseline_dst_impacted.xml", + "kitchen_fans_quantity": 0, + "lighting_present": true, + "lighting_exterior_fraction_cfl": 0.4, + "lighting_garage_fraction_cfl": 0.4, + "lighting_interior_fraction_cfl": 0.4, + "lighting_exterior_fraction_led": 0.25, + "lighting_garage_fraction_led": 0.25, + "lighting_interior_fraction_led": 0.25, + "lighting_exterior_fraction_lfl": 0.1, + "lighting_garage_fraction_lfl": 0.1, + "lighting_interior_fraction_lfl": 0.1, + "lighting_exterior_usage_multiplier": 1.0, + "lighting_garage_usage_multiplier": 1.0, + "lighting_interior_usage_multiplier": 1.0, + "mech_vent_fan_power": 30, + "mech_vent_2_fan_power": 30, + "mech_vent_fan_type": "none", + "mech_vent_2_fan_type": "none", + "mech_vent_flow_rate": 110, + "mech_vent_2_flow_rate": 110, + "mech_vent_hours_in_operation": 24, + "mech_vent_2_hours_in_operation": 24, + "mech_vent_num_units_served": 1, + "mech_vent_sensible_recovery_efficiency": 0.72, + "mech_vent_2_sensible_recovery_efficiency": 0.72, + "mech_vent_recovery_efficiency_type": "Unadjusted", + "mech_vent_2_recovery_efficiency_type": "Unadjusted", + "mech_vent_total_recovery_efficiency": 0.48, + "mech_vent_2_total_recovery_efficiency": 0.48, + "neighbor_back_distance": 0, + "neighbor_front_distance": 0, + "neighbor_left_distance": 10, + "neighbor_right_distance": 10, + "overhangs_back_depth": 2, + "overhangs_back_distance_to_top_of_window": 0, + "overhangs_back_distance_to_bottom_of_window": 4, + "overhangs_front_depth": 2, + "overhangs_front_distance_to_top_of_window": 0, + "overhangs_front_distance_to_bottom_of_window": 4, + "overhangs_left_depth": 2, + "overhangs_left_distance_to_top_of_window": 0, + "overhangs_left_distance_to_bottom_of_window": 4, + "overhangs_right_depth": 2, + "overhangs_right_distance_to_top_of_window": 0, + "overhangs_right_distance_to_bottom_of_window": 4, + "misc_plug_loads_other_annual_kwh": 2457.0, + "misc_plug_loads_other_frac_latent": 0.045, + "misc_plug_loads_other_frac_sensible": 0.855, + "misc_plug_loads_other_usage_multiplier": 1.0, + "misc_plug_loads_television_present": true, + "misc_plug_loads_television_annual_kwh": 620.0, + "misc_plug_loads_television_usage_multiplier": 1.0, + "misc_plug_loads_vehicle_present": false, + "misc_plug_loads_vehicle_usage_multiplier": 0.0, + "misc_plug_loads_well_pump_present": false, + "misc_plug_loads_well_pump_usage_multiplier": 0.0, + "pool_heater_type": "electric resistance", + "pool_heater_usage_multiplier": 1.0, + "pool_present": false, + "pool_pump_usage_multiplier": 1.0, + "pv_system_present": false, + "pv_system_2_present": false, + "pv_system_array_azimuth": 180, + "pv_system_2_array_azimuth": 180, + "pv_system_array_tilt": 20, + "pv_system_2_array_tilt": 20, + "pv_system_inverter_efficiency": 0.96, + "pv_system_max_power_output": 4000, + "pv_system_2_max_power_output": 4000, + "pv_system_num_bedrooms_served": 3, + "pv_system_system_losses_fraction": 0.14, + "battery_present": false, + "refrigerator_present": true, + "refrigerator_location": "conditioned space", + "refrigerator_rated_annual_kwh": 650.0, + "refrigerator_usage_multiplier": 1.0, + "rim_joist_assembly_r": 23.0, + "roof_assembly_r": 2.3, + "roof_color": "medium", + "roof_material_type": "asphalt or fiberglass shingles", + "radiant_barrier_attic_location": "none", + "radiant_barrier_grade": "1", + "hvac_control_cooling_weekday_setpoint": "78", + "hvac_control_cooling_weekend_setpoint": "78", + "hvac_control_heating_weekday_setpoint": "68", + "hvac_control_heating_weekend_setpoint": "68", + "simulation_control_timestep": 60, + "site_type": "suburban", + "skylight_area_back": 0, + "skylight_area_front": 0, + "skylight_area_left": 0, + "skylight_area_right": 0, + "skylight_shgc": 0.45, + "skylight_ufactor": 0.33, + "slab_carpet_fraction": 0.0, + "slab_carpet_r": 0.0, + "slab_perimeter_insulation_depth": 0, + "slab_perimeter_insulation_r": 0, + "slab_thickness": 4.0, + "slab_under_insulation_r": 0, + "slab_under_insulation_width": 0, + "solar_thermal_collector_area": 40.0, + "solar_thermal_collector_azimuth": 180, + "solar_thermal_collector_loop_type": "liquid direct", + "solar_thermal_collector_rated_optical_efficiency": 0.5, + "solar_thermal_collector_rated_thermal_losses": 0.2799, + "solar_thermal_collector_tilt": 20, + "solar_thermal_collector_type": "evacuated tube", + "solar_thermal_solar_fraction": 0, + "solar_thermal_system_type": "none", + "wall_assembly_r": 23, + "wall_color": "medium", + "wall_siding_type": "wood siding", + "wall_type": "WoodStud", + "water_fixtures_shower_low_flow": true, + "water_fixtures_sink_low_flow": false, + "water_fixtures_usage_multiplier": 1.0, + "water_heater_efficiency": 0.95, + "water_heater_efficiency_type": "EnergyFactor", + "water_heater_fuel_type": "electricity", + "water_heater_jacket_rvalue": 0, + "water_heater_location": "conditioned space", + "water_heater_recovery_efficiency": 0.76, + "water_heater_setpoint_temperature": 125, + "water_heater_standby_loss": 0, + "water_heater_tank_volume": 40, + "water_heater_type": "instantaneous water heater", + "weather_station_epw_filepath": "USA_CO_Denver.Intl.AP.725650_TMY3.epw", + "whole_house_fan_flow_rate": 4500, + "whole_house_fan_power": 300, + "whole_house_fan_present": false, + "window_area_back": 0.0, + "window_area_front": 0.0, + "window_area_left": 0.0, + "window_area_right": 0.0, + "window_aspect_ratio": 1.333, + "window_back_wwr": 0.12, + "window_fraction_operable": 0.67, + "window_front_wwr": 0.12, + "window_interior_shading_summer": 0.7, + "window_interior_shading_winter": 0.85, + "window_left_wwr": 0.12, + "window_right_wwr": 0.12, + "window_shgc": 0.45, + "window_ufactor": 0.33 + }, + "measure_dir_name": "BuildResidentialHPXML" + }, + { + "measure_dir_name": "ResStockArgumentsPostHPXML", + "arguments": { + "hpxml_path": "tests/baseline_dst_impacted.xml", + "loadflex_peak_offset": 0, + "loadflex_pre_peak_duration_hours": 0, + "loadflex_pre_peak_offset": 0, + "loadflex_random_shift_minutes": 0, + "output_csv_path": "tests", + "building_id": 1 + } + }, + { + "arguments": { + "hpxml_path": "measures/ResStockArgumentsPostHPXML/tests/baseline_dst_impacted.xml", + "output_dir": "measures/ResStockArgumentsPostHPXML/tests", + "debug": "true" + }, + "measure_dir_name": "HPXMLtoOpenStudio" + } + ] +} \ No newline at end of file diff --git a/measures/ResStockArgumentsPostHPXML/tests/test_hvac_load_flexibility.rb b/measures/ResStockArgumentsPostHPXML/tests/test_hvac_load_flexibility.rb index ae325c717a..d29bd4bc54 100644 --- a/measures/ResStockArgumentsPostHPXML/tests/test_hvac_load_flexibility.rb +++ b/measures/ResStockArgumentsPostHPXML/tests/test_hvac_load_flexibility.rb @@ -8,49 +8,59 @@ require_relative '../measure.rb' require 'pathname' - class ResStockArgumentsPostHPXMLTest < Minitest::Test def setup @runner = OpenStudio::Measure::OSRunner.new(OpenStudio::WorkflowJSON.new) parent_path = File.expand_path("../../../../", __FILE__) epw_path = File.join(parent_path, "resources/hpxml-measures/weather/USA_CO_Denver.Intl.AP.725650_TMY3.epw") weather = WeatherFile.new(epw_path: epw_path, runner: nil) + dst_info = DSTInfo.new(dst_begin_month: 3, + dst_begin_day: 12, + dst_end_month: 11, + dst_end_day: 5) @schedule_modifier_15 = HVACScheduleModifier.new(state:'CO', sim_year:2024, weather: weather, epw_path: epw_path, minutes_per_step:15, - runner:@runner) + runner:@runner, + dst_info:dst_info) @schedule_modifier_60 = HVACScheduleModifier.new(state:'CO', sim_year:2024, weather: weather, epw_path: epw_path, minutes_per_step:60, - runner:@runner) + runner:@runner, + dst_info:dst_info) @non_leap_modifier = HVACScheduleModifier.new(state:'CO', sim_year:2023, weather: weather, epw_path: epw_path, minutes_per_step:15, - runner:@runner) + runner:@runner, + dst_info:dst_info) end def test_get_peak_hour - assert_equal(18, @schedule_modifier_15._get_peak_hour(month: 6)) - assert_equal(19, @schedule_modifier_15._get_peak_hour(month: 1)) + assert_equal([18, 22], @schedule_modifier_15._get_peak_hour(0, month: 6)) #shed summer + assert_equal([18, 22], @schedule_modifier_15._get_peak_hour(0, month: 1)) #shed winter + assert_equal([16, 20], @schedule_modifier_15._get_peak_hour(0, month: 5)) #shed intermediate + assert_equal([16, 20], @schedule_modifier_15._get_peak_hour(4, month: 6)) #shift summer + assert_equal([17, 21], @schedule_modifier_15._get_peak_hour(4, month: 1)) #shift winter + assert_equal([16, 20], @schedule_modifier_15._get_peak_hour(4, month: 5)) #shift intermediate end - def test_get_month - assert_equal(2, @schedule_modifier_15._get_month(index: 31 * 24 * 4 + 28 * 24 * 4 + 1)) # First 15 minutes of Feb 29 - assert_equal(2, @schedule_modifier_60._get_month(index: 31 * 24 + 28 * 24 + 1)) # First 1 hour of Feb 29 - assert_equal(3, @non_leap_modifier._get_month(index: 31 * 24 *4 + 28 * 24 * 4 + 1)) # First 15 minutes of March 1 + def test_get_month_day + assert_equal([2, 29], @schedule_modifier_15._get_month_day(index: 31 * 24 * 4 + 28 * 24 * 4 + 1)) # First 15 minutes of Feb 29 + assert_equal([2, 29], @schedule_modifier_60._get_month_day(index: 31 * 24 + 28 * 24 + 1)) # First 1 hour of Feb 29 + assert_equal([3, 1], @non_leap_modifier._get_month_day(index: 31 * 24 * 4 + 28 * 24 * 4 + 1)) # First 15 minutes of March 1 - assert_equal(12, @schedule_modifier_15._get_month(index: 366 * 24 * 4 - 1)) - assert_equal(12, @non_leap_modifier._get_month(index: 365 * 24 * 4 - 1)) + assert_equal([12, 31], @schedule_modifier_15._get_month_day(index: 366 * 24 * 4 - 1)) + assert_equal([12, 31], @non_leap_modifier._get_month_day(index: 365 * 24 * 4 - 1)) - assert_equal(1, @schedule_modifier_15._get_month(index: 0)) - assert_equal(1, @non_leap_modifier._get_month(index: 0)) + assert_equal([1, 1], @schedule_modifier_15._get_month_day(index: 0)) + assert_equal([1, 1], @non_leap_modifier._get_month_day(index: 0)) end def test_modify_setpoints @@ -62,21 +72,20 @@ def test_modify_setpoints flexibility_inputs = FlexibilityInputs.new( random_shift_steps: 0, pre_peak_duration_steps: 4 * 4, - peak_duration_steps: 2 * 4, pre_peak_offset: 3, peak_offset: 4 ) - + pds = 4 * 4 # peak duration steps modified_setpoints_15 = @schedule_modifier_15.modify_setpoints(setpoints, flexibility_inputs) - winter_peak = 4 * @schedule_modifier_15._get_peak_hour(month: 1) - summer_peak = 4 * @schedule_modifier_15._get_peak_hour(month: 7) - + winter_peak = 4 * @schedule_modifier_15._get_peak_hour(flexibility_inputs.pre_peak_duration_steps, month: 1)[0] + summer_peak = 4 * @schedule_modifier_15._get_peak_hour(flexibility_inputs.pre_peak_duration_steps, month: 7)[0] + summer_peak += 4 # daylight saving time summer_midnight = 3 * 31 * 24 * 4 + 29 * 24 * 4 + 3 * 30 * 24 * 4 # index from Jan to Jun assert_equal(71, modified_setpoints_15[:heating_setpoint][0]) assert_equal(78, modified_setpoints_15[:cooling_setpoint][0]) - assert_equal(78, modified_setpoints_15[:cooling_setpoint][winter_peak]) # peak offset + assert_equal(78 + 4, modified_setpoints_15[:cooling_setpoint][winter_peak]) # peak offset assert_equal(71 - 4 , modified_setpoints_15[:heating_setpoint][winter_peak]) # peak offset assert_equal(78, modified_setpoints_15[:cooling_setpoint][winter_peak - 1]) # pre-peak offset assert_equal(71 + 3, modified_setpoints_15[:heating_setpoint][winter_peak - 1]) # pre-peak offset @@ -84,21 +93,20 @@ def test_modify_setpoints assert_equal(71, modified_setpoints_15[:heating_setpoint][summer_midnight]) assert_equal(78, modified_setpoints_15[:cooling_setpoint][summer_midnight]) assert_equal(78 + 4, modified_setpoints_15[:cooling_setpoint][summer_midnight + summer_peak]) # peak offset - assert_equal(71, modified_setpoints_15[:heating_setpoint][summer_midnight + summer_peak]) # peak offset + assert_equal(71 - 4, modified_setpoints_15[:heating_setpoint][summer_midnight + summer_peak]) # peak offset assert_equal(78 - 3, modified_setpoints_15[:cooling_setpoint][summer_midnight + summer_peak - 1]) # pre-peak offset assert_equal(71, modified_setpoints_15[:heating_setpoint][summer_midnight + summer_peak - 1]) # pre-peak offset flexibility_inputs = FlexibilityInputs.new( random_shift_steps: 2, pre_peak_duration_steps: 4 * 4, - peak_duration_steps: 2 * 4, pre_peak_offset: 3, peak_offset: 4 ) modified_setpoints_15 = @schedule_modifier_15.modify_setpoints(setpoints, flexibility_inputs) assert_equal(71, modified_setpoints_15[:heating_setpoint][0]) assert_equal(78, modified_setpoints_15[:cooling_setpoint][0]) - assert_equal(78, modified_setpoints_15[:cooling_setpoint][winter_peak + 2]) # peak offset + assert_equal(78 + 4, modified_setpoints_15[:cooling_setpoint][winter_peak + 2]) # peak offset assert_equal(71 - 4, modified_setpoints_15[:heating_setpoint][winter_peak + 2]) # peak offset assert_equal(78, modified_setpoints_15[:cooling_setpoint][winter_peak + 2 - 4 * 4]) # start of pre-peak offset assert_equal(71 + 3, modified_setpoints_15[:heating_setpoint][winter_peak + 2 - 1]) # end of pre-peak offset @@ -106,21 +114,26 @@ def test_modify_setpoints assert_equal(71, modified_setpoints_15[:heating_setpoint][summer_midnight]) assert_equal(78, modified_setpoints_15[:cooling_setpoint][summer_midnight]) assert_equal(78 + 4, modified_setpoints_15[:cooling_setpoint][summer_midnight + summer_peak + 2]) # start of peak period - assert_equal(71, modified_setpoints_15[:heating_setpoint][summer_midnight + summer_peak + 2 + 2 * 4 - 1]) # end of peak period + assert_equal(78 - 3, modified_setpoints_15[:cooling_setpoint][summer_midnight + summer_peak + 2 - 1]) # End of pre-peak period + assert_equal(71 - 4, modified_setpoints_15[:heating_setpoint][summer_midnight + summer_peak + 2 + 2 * 4 - 1]) # end of peak period assert_equal(78 - 0, modified_setpoints_15[:cooling_setpoint][summer_midnight + summer_peak + 2 - 4 * 4 - 1]) # before pre-peak period - assert_equal(71, modified_setpoints_15[:heating_setpoint][summer_midnight + summer_peak + 2 + 2 * 4]) # after peak period + assert_equal(71, modified_setpoints_15[:heating_setpoint][summer_midnight + summer_peak + 2 + pds]) # after peak period flexibility_inputs = FlexibilityInputs.new( random_shift_steps: -2, pre_peak_duration_steps: 0, - peak_duration_steps: 2 * 4, pre_peak_offset: 3, # unused since pre_peak_duration_steps is 0 peak_offset: 2 ) + + winter_peak = 4 * @schedule_modifier_15._get_peak_hour(flexibility_inputs.pre_peak_duration_steps, month: 1)[0] + summer_peak = 4 * @schedule_modifier_15._get_peak_hour(flexibility_inputs.pre_peak_duration_steps, month: 7)[0] + summer_peak += 4 # daylight saving time + modified_setpoints_15 = @schedule_modifier_15.modify_setpoints(setpoints, flexibility_inputs) assert_equal(71, modified_setpoints_15[:heating_setpoint][0]) assert_equal(78, modified_setpoints_15[:cooling_setpoint][0]) - assert_equal(78, modified_setpoints_15[:cooling_setpoint][winter_peak - 2]) # peak offset + assert_equal(78 + 2, modified_setpoints_15[:cooling_setpoint][winter_peak - 2]) # peak offset assert_equal(71 - 2, modified_setpoints_15[:heating_setpoint][winter_peak - 2]) # peak offset assert_equal(78, modified_setpoints_15[:cooling_setpoint][winter_peak - 2 - 1]) # end of pre-peak period assert_equal(71 + 0, modified_setpoints_15[:heating_setpoint][winter_peak - 2 - 1]) # end of pre-peak period @@ -128,9 +141,39 @@ def test_modify_setpoints assert_equal(71, modified_setpoints_15[:heating_setpoint][summer_midnight]) assert_equal(78, modified_setpoints_15[:cooling_setpoint][summer_midnight]) assert_equal(78 + 2, modified_setpoints_15[:cooling_setpoint][summer_midnight + summer_peak - 2]) # peak offset - assert_equal(71, modified_setpoints_15[:heating_setpoint][summer_midnight + summer_peak - 2]) # peak offset + assert_equal(71 - 2, modified_setpoints_15[:heating_setpoint][summer_midnight + summer_peak - 2]) # peak offset assert_equal(78 - 0, modified_setpoints_15[:cooling_setpoint][summer_midnight + summer_peak - 2 - 1]) # before peak period assert_equal(71, modified_setpoints_15[:heating_setpoint][summer_midnight + summer_peak - 2 - 1]) # before peak period end + def test_clip_setpoints + assert_equal(82, @schedule_modifier_15._clip_setpoints(88)) + assert_equal(55, @schedule_modifier_15._clip_setpoints(45)) + assert_equal(65, @schedule_modifier_15._clip_setpoints(65)) + assert_equal(82, @schedule_modifier_15._clip_setpoints(88)) + assert_equal(55, @schedule_modifier_15._clip_setpoints(45)) + assert_equal(65, @schedule_modifier_15._clip_setpoints(65)) + end + + def test_get_peak_times + flexibility_inputs = FlexibilityInputs.new( + random_shift_steps: 0, + pre_peak_duration_steps: 4 * 4, + pre_peak_offset: 3, + peak_offset: 4 + ) + + peak_times = @schedule_modifier_15._get_peak_times(1, flexibility_inputs) # peak time in Jan + assert_equal(17 * 4, peak_times.peak_start_index) + assert_equal(21 * 4, peak_times.peak_end_index) + assert_equal(13 * 4, peak_times.pre_peak_start_index) + + peak_times = @schedule_modifier_15._get_peak_times((30 * 4 + 15 ) * 24 * 4, flexibility_inputs) # peak time in May + # +4 because of the daylight saving time + assert_equal(16 * 4 + 4, peak_times.peak_start_index) + assert_equal(20 * 4 + 4, peak_times.peak_end_index) + assert_equal(12 * 4 + 4, peak_times.pre_peak_start_index) + + end + end diff --git a/measures/ResStockArgumentsPostHPXML/tests/test_measure.rb b/measures/ResStockArgumentsPostHPXML/tests/test_measure.rb new file mode 100644 index 0000000000..80cae6aa2c --- /dev/null +++ b/measures/ResStockArgumentsPostHPXML/tests/test_measure.rb @@ -0,0 +1,169 @@ +# frozen_string_literal: true + +require 'openstudio' +require_relative '../../../resources/hpxml-measures/HPXMLtoOpenStudio/resources/minitest_helper' +require_relative '../../../resources/buildstock.rb' +require_relative '../measure.rb' + +class ResStockArgumentsPostHPXMLTest < Minitest::Test + def test_load_flexibility_measure + # daylight_saving is false + osw_file = 'baseline.osw' + puts "\nTesting #{File.basename(osw_file)}..." + _test_measure(osw_file) + end + + def test_load_flexibility_measure_dst_impacted + # daylight_saving is true + osw_file = 'baseline_dst_impacted.osw' + puts "\nTesting #{File.basename(osw_file)}..." + _test_measure(osw_file) + end + + private + + + def _run_osw(model, osw) + measures = {} + + osw_hash = JSON.parse(File.read(osw)) + measures_dirs = osw_hash['measure_paths'].map { |path| File.join(File.dirname(__FILE__), path) } + osw_hash['steps'].each do |step| + measures[step['measure_dir_name']] = [step['arguments']] + end + runner = OpenStudio::Measure::OSRunner.new(OpenStudio::WorkflowJSON.new) + + # Apply measure + cdir = File.expand_path('.') + success = apply_measures(measures_dirs, measures, runner, model) + Dir.chdir(cdir) # we need this because of Dir.chdir in HPXMLtoOS + + # Report warnings/errors + runner.result.stepWarnings.each do |s| + puts "Warning: #{s}" + end + runner.result.stepErrors.each do |s| + puts "Error: #{s}" + end + + assert(success) + end + + + def _upgrade_osw(osw, loadflex_peak_offset, loadflex_pre_peak_duration_hours, loadflex_pre_peak_offset) + upgrades = { 'loadflex_peak_offset' => loadflex_peak_offset, + 'loadflex_pre_peak_duration_hours' => loadflex_pre_peak_duration_hours, + 'loadflex_pre_peak_offset' => loadflex_pre_peak_offset } + puts upgrades + + osw_hash = JSON.parse(File.read(osw)) + osw_hash['steps'].each do |step| + step['arguments']['hpxml_path'] = step['arguments']['hpxml_path'].gsub('tests/', 'tests/Upgrade_') + if step['measure_dir_name'] == 'ResStockArgumentsPostHPXML' + step['arguments'].update(upgrades) + end + end + File.open(osw, 'w') { |json| json.write(JSON.pretty_generate(osw_hash)) } + end + + + def _test_measure(osw_file) + require 'json' + require 'csv' + + puts "\nTesting #{osw_file}..." + this_dir = File.dirname(__FILE__) + + values = { 'hpxml_output' => {} } + + # Existing + model = OpenStudio::Model::Model.new + osw = File.absolute_path("#{this_dir}/#{osw_file}") + _run_osw(model, osw) + + hpxml_path = File.join(this_dir, 'in.xml') + hpxml_in = HPXML.new(hpxml_path: hpxml_path) + + existing_path = File.join(this_dir, osw_file.gsub('osw', 'xml')) + existing_hpxml = HPXML.new(hpxml_path: existing_path) + + # Upgraded with load flexibility measure + upgrade_osw_file = "Upgrade_#{osw_file}" + upgrade_osw = File.absolute_path("#{this_dir}/#{upgrade_osw_file}") + FileUtils.cp(osw, upgrade_osw) + + loadflex_peak_offset = 2 + loadflex_pre_peak_duration_hours = 2 + loadflex_pre_peak_offset = 3 + + _upgrade_osw(upgrade_osw, loadflex_peak_offset, loadflex_pre_peak_duration_hours, loadflex_pre_peak_offset) + _run_osw(model, upgrade_osw) + + upgraded_path = File.join(this_dir, upgrade_osw_file.gsub('osw', 'xml')) + upgraded_hpxml = HPXML.new(hpxml_path: upgraded_path) + + # Create instance of the measures + load_flexibility = ResStockArgumentsPostHPXML.new + + # validate setpoint temperature is modified according to measure + schedule_file_path = File.join(this_dir, 'in.schedules.csv') + # indices for setpint 01-01 14:00:00-15:00:00, 15:00:00-16:00:00, 17:00:00-18:00:00 + # the on-peak hour in CO in winter starts from 17:00:00 + heating_indices = [14, 15, 16, 17] + # indices for 05-09 13:00:00-14:00:00, 14:00:00-15:00:00, 16:00:00-17:00:00, + # the on-peak hour in CO in summer starts from 16:00:00 + cooling_indices = [3085, 3086, 3087, 3088] + + # if daylight savings is impacted, add 1 hour to on-peak start and end time + # the on-peak hour in CO in summer starts from 16:00:00, but it should start from 17:00:00 due to daylight savings + if osw_file.include?("dst_impacted") + cooling_indices = cooling_indices.map { |num| num + 1 } + end + + heating_rows = [] + cooling_rows = [] + + CSV.foreach(schedule_file_path, headers: true).with_index do |row, index| + if heating_indices.include?(index) + heating_rows << row.to_h + end + end + CSV.foreach(schedule_file_path, headers: true).with_index do |row, index| + if cooling_indices.include?(index) + cooling_rows << row.to_h + end + end + + heating_setpoint_base = celsius_to_fahrenheit(heating_rows[0]["heating_setpoint"].to_f) + heating_setpoint_pre_peak = celsius_to_fahrenheit(heating_rows[1]["heating_setpoint"].to_f) + heating_setpoint_on_peak = celsius_to_fahrenheit(heating_rows[3]["heating_setpoint"].to_f) + + cooling_setpoint_base = celsius_to_fahrenheit(cooling_rows[0]["cooling_setpoint"].to_f) + cooling_setpoint_pre_peak = celsius_to_fahrenheit(cooling_rows[1]["cooling_setpoint"].to_f) + cooling_setpoint_on_peak = celsius_to_fahrenheit(cooling_rows[3]["cooling_setpoint"].to_f) + + puts "Testing heating pre peak setpoint offset" + assert_equal(loadflex_pre_peak_offset, heating_setpoint_pre_peak - heating_setpoint_base) + puts "Testing heating on peak setpoint offset" + assert_equal(loadflex_peak_offset, heating_setpoint_base - heating_setpoint_on_peak) + + puts "Testing cooling pre peak setpoint offset" + assert_equal(loadflex_pre_peak_offset, cooling_setpoint_base - cooling_setpoint_pre_peak) + puts "Testing cooling on peak setpoint offset" + assert_equal(loadflex_peak_offset, cooling_setpoint_on_peak - cooling_setpoint_base) + + # Clean up + File.delete(File.join(File.dirname(__FILE__), osw_file.gsub('.osw', '.xml'))) + File.delete(File.join(File.dirname(__FILE__), upgrade_osw_file)) + File.delete(File.join(File.dirname(__FILE__), upgrade_osw_file.gsub('.osw', '.xml'))) + Dir.glob(File.join(File.dirname(__FILE__), 'in.*')).each { |f| File.delete(f) } + Dir.glob(File.join(File.dirname(__FILE__), '*.csv')).each { |f| File.delete(f) } + + end + + def celsius_to_fahrenheit(celsius) + fahrenheit = (celsius * 9.0 / 5.0) + 32 + return fahrenheit.round + end + +end \ No newline at end of file diff --git a/project_national/pre_peak_sensitivity_test.yml b/project_national/pre_peak_sensitivity_test.yml index 772b792c5f..d58a25cb6e 100644 --- a/project_national/pre_peak_sensitivity_test.yml +++ b/project_national/pre_peak_sensitivity_test.yml @@ -4,15 +4,15 @@ os_sha: c77fbb9569 buildstock_directory: ../ # Relative to this file or absolute project_directory: project_national # Relative to buildstock_directory #output_directory: /Volumes/LaCie/load_flexibility/pre_peak_sensitivity_dec24 -output_directory: /projects/rescore/load_flex/pre_peak_sensitivity_dec29 +output_directory: /projects/rescore/load_flex/pre_peak_sensitivity_jan31 # weather_files_path: /Users/radhikar/Documents/BuildStock_TMY3_FIPS.zip -weather_files_path: kfs2/shared-projects/buildstock/weather/BuildStock_2020_FIPS.zip +weather_files_path: /kfs2/shared-projects/buildstock/weather/BuildStock_2020_FIPS.zip # weather_files_path: c:/OpenStudio/BuildStock_TMY3_FIPS.zip sampler: type: residential_quota args: - n_datapoints: 1000 + n_datapoints: 5000 kestrel: @@ -21,7 +21,7 @@ kestrel: account: rescore postprocessing: time: 120 - n_workers: 5 + n_workers: 10 n_procs: 20 sampling: time: 30 @@ -73,57 +73,42 @@ baseline: n_buildings_represented: 139647020 # American Community Survey 2021 5-year, B25001, does not include territories ( 138765649 without AK and HI ) upgrades: - - upgrade_name: scenario1 + - upgrade_name: peak_only_4hr_2deg options: - - option: LoadFlexibility|scenario1 - - upgrade_name: scenario2 + - option: LoadFlexibility|peak_only_4hr_2deg + - upgrade_name: pre_only_4hr_2deg options: - - option: LoadFlexibility|scenario2 - - upgrade_name: scenario3 + - option: LoadFlexibility|pre_only_4hr_2deg + - upgrade_name: both_4hr_2deg options: - - option: LoadFlexibility|scenario3 - - upgrade_name: scenario4 + - option: LoadFlexibility|both_4hr_2deg + - upgrade_name: peak_only_4hr_4deg options: - - option: LoadFlexibility|scenario4 - - upgrade_name: scenario5 + - option: LoadFlexibility|peak_only_4hr_4deg + - upgrade_name: pre_only_4hr_4deg options: - - option: LoadFlexibility|scenario5 - - upgrade_name: scenario6 + - option: LoadFlexibility|pre_only_4hr_4deg + - upgrade_name: both_4hr_4deg options: - - option: LoadFlexibility|scenario6 - - upgrade_name: scenario7 + - option: LoadFlexibility|both_4hr_4deg + - upgrade_name: peak_only_1hr_2deg options: - - option: LoadFlexibility|scenario7 - - upgrade_name: scenario8 + - option: LoadFlexibility|peak_only_1hr_2deg + - upgrade_name: pre_only_1hr_2deg options: - - option: LoadFlexibility|scenario8 - - upgrade_name: scenario9 + - option: LoadFlexibility|pre_only_1hr_2deg + - upgrade_name: both_1hr_2deg options: - - option: LoadFlexibility|scenario9 - - upgrade_name: scenario10 + - option: LoadFlexibility|both_1hr_2deg + - upgrade_name: peak_only_1hr_4deg options: - - option: LoadFlexibility|scenario10 - - upgrade_name: scenario11 + - option: LoadFlexibility|peak_only_1hr_4deg + - upgrade_name: pre_only_1hr_4deg options: - - option: LoadFlexibility|scenario11 - - upgrade_name: scenario12 + - option: LoadFlexibility|pre_only_1hr_4deg + - upgrade_name: both_1hr_4deg options: - - option: LoadFlexibility|scenario12 - - upgrade_name: scenario13 - options: - - option: LoadFlexibility|scenario13 - - upgrade_name: scenario14 - options: - - option: LoadFlexibility|scenario14 - - upgrade_name: scenario15 - options: - - option: LoadFlexibility|scenario15 - - upgrade_name: scenario16 - options: - - option: LoadFlexibility|scenario16 - - upgrade_name: scenario17 - options: - - option: LoadFlexibility|scenario17 + - option: LoadFlexibility|both_1hr_4deg postprocessing: keep_individual_timeseries: true diff --git a/resources/options_lookup.tsv b/resources/options_lookup.tsv index 6d4ff14b81..d88c47b78d 100644 --- a/resources/options_lookup.tsv +++ b/resources/options_lookup.tsv @@ -13972,22 +13972,17 @@ Windows "Triple, Low-E, Insulated, Argon, L-Gain" ResStockArguments window_ufact Windows "Triple, Low-E, Non-metal, Air, L-Gain" ResStockArguments window_ufactor=0.29 window_shgc=0.26 skylight_ufactor=0.37 skylight_shgc=0.3 skylight_storm_type=auto window_exterior_shading_type=auto window_exterior_shading_summer=auto window_exterior_shading_winter=auto window_natvent_availability=auto window_shading_summer_season=auto window_insect_screens=auto Windows No Windows ResStockArguments window_ufactor=0.84 window_shgc=0.63 skylight_ufactor=0.37 skylight_shgc=0.3 skylight_storm_type=auto window_exterior_shading_type=auto window_exterior_shading_summer=auto window_exterior_shading_winter=auto window_natvent_availability=auto window_shading_summer_season=auto window_insect_screens=auto Windows Void -LoadFlexibility short_mild ResStockArgumentsPostHPXML loadflex_peak_duration_hours=1 loadflex_peak_offset=2 loadflex_pre_peak_duration_hours=2 loadflex_pre_peak_offset=2 -LoadFlexibility no_pre_peak_medium_moderate ResStockArgumentsPostHPXML loadflex_peak_duration_hours=1 loadflex_peak_offset=2 loadflex_pre_peak_duration_hours= loadflex_pre_peak_offset= -LoadFlexibility scenario1 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=2 loadflex_pre_peak_duration_hours=0 loadflex_pre_peak_offset=2 -LoadFlexibility scenario2 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=2 loadflex_pre_peak_duration_hours=0.25 loadflex_pre_peak_offset=2 -LoadFlexibility scenario3 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=2 loadflex_pre_peak_duration_hours=0.5 loadflex_pre_peak_offset=2 -LoadFlexibility scenario4 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=2 loadflex_pre_peak_duration_hours=1 loadflex_pre_peak_offset=2 -LoadFlexibility scenario5 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=2 loadflex_pre_peak_duration_hours=2 loadflex_pre_peak_offset=2 -LoadFlexibility scenario6 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=2 loadflex_pre_peak_duration_hours=4 loadflex_pre_peak_offset=2 -LoadFlexibility scenario7 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=4 loadflex_pre_peak_duration_hours=0 loadflex_pre_peak_offset=4 -LoadFlexibility scenario8 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=4 loadflex_pre_peak_duration_hours=0.25 loadflex_pre_peak_offset=4 -LoadFlexibility scenario9 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=4 loadflex_pre_peak_duration_hours=0.5 loadflex_pre_peak_offset=4 -LoadFlexibility scenario10 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=4 loadflex_pre_peak_duration_hours=1 loadflex_pre_peak_offset=4 -LoadFlexibility scenario11 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=4 loadflex_pre_peak_duration_hours=2 loadflex_pre_peak_offset=4 -LoadFlexibility scenario12 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=4 loadflex_pre_peak_duration_hours=4 loadflex_pre_peak_offset=4 -LoadFlexibility scenario13 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=4 loadflex_pre_peak_duration_hours=0.25 loadflex_pre_peak_offset=6 -LoadFlexibility scenario14 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=4 loadflex_pre_peak_duration_hours=0.5 loadflex_pre_peak_offset=6 -LoadFlexibility scenario15 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=4 loadflex_pre_peak_duration_hours=1 loadflex_pre_peak_offset=6 -LoadFlexibility scenario16 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=4 loadflex_pre_peak_duration_hours=2 loadflex_pre_peak_offset=6 -LoadFlexibility scenario17 ResStockArgumentsPostHPXML loadflex_peak_duration_hours=4 loadflex_peak_offset=4 loadflex_pre_peak_duration_hours=4 loadflex_pre_peak_offset=6 +LoadFlexibility short_mild ResStockArgumentsPostHPXML loadflex_peak_offset=2 loadflex_pre_peak_duration_hours=2 loadflex_pre_peak_offset=2 +LoadFlexibility no_pre_peak_medium_moderate ResStockArgumentsPostHPXML loadflex_peak_offset=2 loadflex_pre_peak_duration_hours= loadflex_pre_peak_offset= +LoadFlexibility peak_only_4hr_2deg ResStockArgumentsPostHPXML loadflex_peak_offset=2 loadflex_pre_peak_duration_hours=0 loadflex_pre_peak_offset=0 loadflex_random_shift_minutes=30 +LoadFlexibility pre_only_4hr_2deg ResStockArgumentsPostHPXML loadflex_peak_offset=0 loadflex_pre_peak_duration_hours=4 loadflex_pre_peak_offset=2 loadflex_random_shift_minutes=30 +LoadFlexibility both_4hr_2deg ResStockArgumentsPostHPXML loadflex_peak_offset=2 loadflex_pre_peak_duration_hours=4 loadflex_pre_peak_offset=2 loadflex_random_shift_minutes=30 +LoadFlexibility peak_only_4hr_4deg ResStockArgumentsPostHPXML loadflex_peak_offset=4 loadflex_pre_peak_duration_hours=0 loadflex_pre_peak_offset=0 loadflex_random_shift_minutes=30 +LoadFlexibility pre_only_4hr_4deg ResStockArgumentsPostHPXML loadflex_peak_offset=0 loadflex_pre_peak_duration_hours=4 loadflex_pre_peak_offset=4 loadflex_random_shift_minutes=30 +LoadFlexibility both_4hr_4deg ResStockArgumentsPostHPXML loadflex_peak_offset=4 loadflex_pre_peak_duration_hours=4 loadflex_pre_peak_offset=4 loadflex_random_shift_minutes=30 +LoadFlexibility peak_only_1hr_2deg ResStockArgumentsPostHPXML loadflex_peak_offset=2 loadflex_pre_peak_duration_hours=0 loadflex_pre_peak_offset=0 loadflex_random_shift_minutes=30 +LoadFlexibility pre_only_1hr_2deg ResStockArgumentsPostHPXML loadflex_peak_offset=0 loadflex_pre_peak_duration_hours=1 loadflex_pre_peak_offset=2 loadflex_random_shift_minutes=30 +LoadFlexibility both_1hr_2deg ResStockArgumentsPostHPXML loadflex_peak_offset=2 loadflex_pre_peak_duration_hours=1 loadflex_pre_peak_offset=2 loadflex_random_shift_minutes=30 +LoadFlexibility peak_only_1hr_4deg ResStockArgumentsPostHPXML loadflex_peak_offset=4 loadflex_pre_peak_duration_hours=0 loadflex_pre_peak_offset=0 loadflex_random_shift_minutes=30 +LoadFlexibility pre_only_1hr_4deg ResStockArgumentsPostHPXML loadflex_peak_offset=0 loadflex_pre_peak_duration_hours=1 loadflex_pre_peak_offset=4 loadflex_random_shift_minutes=30 +LoadFlexibility both_1hr_4deg ResStockArgumentsPostHPXML loadflex_peak_offset=4 loadflex_pre_peak_duration_hours=1 loadflex_pre_peak_offset=4 loadflex_random_shift_minutes=30