# ******************************************************************************* # OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC. # See also https://openstudio.net/license # ******************************************************************************* # see the URL below for information on how to write OpenStudio measures # http://openstudio.nrel.gov/openstudio-measure-writing-guide # see the URL below for access to C++ documentation on model objects (click on "model" in the main window to view model objects) # http://openstudio.nrel.gov/sites/openstudio.nrel.gov/files/nv_data/cpp_documentation_it/model/html/namespaces.html # start the measure class RemoveUnusedDefaultProfiles < OpenStudio::Measure::ModelMeasure # define the name that a user will see, this method may be deprecated as # the display name in PAT comes from the name field in measure.xml def name return 'RemoveUnusedDefaultProfiles' end # define the arguments that the user will input def arguments(model) args = OpenStudio::Measure::OSArgumentVector.new # measure does not have any arguments return args end # define what happens when the measure is run def run(model, runner, user_arguments) super(model, runner, user_arguments) # use the built-in error checking if !runner.validateUserArguments(arguments(model), user_arguments) return false end # no user inputs assign to variables # reporting initial condition of model schedule_rulesets = model.getScheduleRulesets runner.registerInitialCondition("The model has #{schedule_rulesets.size} ScheduleRulesets.") # set start and end dates start_date = OpenStudio::Date.new(OpenStudio::MonthOfYear.new('January'), 1) end_date = OpenStudio::Date.new(OpenStudio::MonthOfYear.new('December'), 31) # year does matter, but I'm not setting it here # counter for removed default profiles default_profiles_removed = 0 # loop through all ScheduleRuleset objects schedule_rulesets.each do |schedule_ruleset| indices_vector = schedule_ruleset.getActiveRuleIndices(start_date, end_date) # line below lets you see the indices if for diagnostic purposes # runner.registerInfo("#{schedule_ruleset.name}: #{indices_vector}") if !indices_vector.include? -1 runner.registerInfo("#{schedule_ruleset.name} does not used the default profile, it will be replaced.") # reset values in default ScheduleDay old_default_schedule_day = schedule_ruleset.defaultDaySchedule old_default_schedule_day.clearValues # get values for new default profile rule_vector = schedule_ruleset.scheduleRules new_default_daySchedule = rule_vector.reverse[0].daySchedule new_default_daySchedule_values = new_default_daySchedule.values new_default_daySchedule_times = new_default_daySchedule.times # update values and times for default profile for i in 0..(new_default_daySchedule_values.size - 1) old_default_schedule_day.addValue(new_default_daySchedule_times[i], new_default_daySchedule_values[i]) end # note - I'm not looking at interpolatetoTimestep field. # confirm that changes were made # runner.registerInfo("Default values for #{schedule_ruleset.name}: #{old_default_schedule_day.values}") # remove rule object that has become the default. Also try to remove the ScheduleDay rule_vector.reverse[0].remove # this seems to also remove the ScheduleDay associated with the rule # new_default_daySchedule.remove default_profiles_removed += 1 end # report warning if schedule is missing type limits if schedule_ruleset.scheduleTypeLimits.empty? runner.registerWarning("#{schedule_ruleset.name} does not have a type limits assigned.") else # store schedule type limits object desired_type_limit = schedule_ruleset.scheduleTypeLimits.get # set type limit for summer and winter design day objects default_day = schedule_ruleset.defaultDaySchedule summer_design_day = schedule_ruleset.summerDesignDaySchedule winter_design_day = schedule_ruleset.winterDesignDaySchedule default_day_type_limit = default_day.setScheduleTypeLimits(desired_type_limit) summer_design_day_type_limit = summer_design_day.setScheduleTypeLimits(desired_type_limit) winter_design_type_limit = winter_design_day.setScheduleTypeLimits(desired_type_limit) if !default_day_type_limit || !summer_design_day_type_limit || !winter_design_type_limit runner.registerWarning("Failed to set type limit for default or design day for #{schedule_ruleset.name}") else puts 'did something' end # get day schedules for schedule_ruleset schedule_rules = schedule_ruleset.scheduleRules schedule_rules.each do |schedule_rule| day_schedule = schedule_rule.daySchedule day_type_limit = day_schedule.setScheduleTypeLimits(desired_type_limit) if !day_type_limit runner.registerWarning("Failed to set type limit for #{day_schedule.name}, child of #{schedule_ruleset.name}.") end end end end # reporting final condition of model runner.registerFinalCondition("#{default_profiles_removed} RuleSetSchedules had unused default profiles.") return true end end # this allows the measure to be use by the application RemoveUnusedDefaultProfiles.new.registerWithApplication