lib/openstudio-standards/space/space.rb in openstudio-standards-0.6.0.rc2 vs lib/openstudio-standards/space/space.rb in openstudio-standards-0.6.3

- old
+ new

@@ -18,11 +18,11 @@ # floor area. This method internally # also checks to see if the space's zone # is a supply or return plenum unless space.partofTotalFloorArea plenum_status = true - return plenum_status + return true end # @todo update to check if it has internal loads # Check if the space type name @@ -32,15 +32,13 @@ space_type = space_type.get if space_type.name.get.to_s.downcase.include?('plenum') plenum_status = true return plenum_status end - if space_type.standardsSpaceType.is_initialized - if space_type.standardsSpaceType.get.downcase.include?('plenum') - plenum_status = true - return plenum_status - end + if space_type.standardsSpaceType.is_initialized && space_type.standardsSpaceType.get.downcase.include?('plenum') + plenum_status = true + return plenum_status end end return plenum_status end @@ -280,11 +278,11 @@ hoo_hours = hoo_end + 24 - hoo_start end rule_hash[:hoo_hours] = hoo_hours days_used = [] indices_vector.each_with_index do |profile_index, i| - if profile_index == -1 then days_used << i + 1 end + if profile_index == -1 then days_used << (i + 1) end end rule_hash[:days_used] = days_used profiles[-1] = rule_hash hours_of_operation.scheduleRules.reverse.each do |rule| @@ -335,11 +333,11 @@ hoo_hours = hoo_end + 24 - hoo_start end rule_hash[:hoo_hours] = hoo_hours days_used = [] indices_vector.each_with_index do |profile_index, i| - if profile_index == rule.ruleIndex then days_used << i + 1 end + if profile_index == rule.ruleIndex then days_used << (i + 1) end end rule_hash[:days_used] = days_used # # todo - delete rule details below unless end up needing to use them # if rule.startDate.is_initialized @@ -421,15 +419,18 @@ # normalized_annual_range evaluates each value against the min/max range for the year # normalized_daily_range evaluates each value against the min/max range for the day. # The goal is a dynamic threshold that calibrates each day. # @return [<OpenStudio::Model::ScheduleRuleset>] a ScheduleRuleset of fractional or discrete occupancy def self.spaces_get_occupancy_schedule(spaces, sch_name: nil, occupied_percentage_threshold: nil, threshold_calc_method: 'value') - unless !spaces.empty? + if spaces.empty? OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.space', 'Empty spaces array passed to spaces_get_occupancy_schedule method.') return false end + model = spaces.first.model + year = model.getYearDescription.assumedYear + unless sch_name.nil? OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.space', "Finding space schedules for #{sch_name}.") end # create schedule @@ -510,31 +511,39 @@ elsif threshold_calc_method == 'normalized_daily_range' # calculate max/min values in each daily occ fraction array daily_max_vals = daily_combined_occ_fracs.map(&:max) daily_min_vals = daily_combined_occ_fracs.map(&:min) # normalize threshold to daily min/max values - daily_normalized_thresholds = daily_min_vals.zip(daily_max_vals).map { |min_max| min_max[0] + (min_max[1] - min_max[0]) * occupied_percentage_threshold } + daily_normalized_thresholds = daily_min_vals.zip(daily_max_vals).map { |min_max| min_max[0] + ((min_max[1] - min_max[0]) * occupied_percentage_threshold) } # if daily occ frac exceeds daily normalized threshold, set value to 1 occ_status_vals = daily_combined_occ_fracs.each_with_index.map { |day_array, i| day_array.map { |day_val| !day_val.zero? && day_val >= daily_normalized_thresholds[i] ? 1 : 0 } } elsif threshold_calc_method == 'normalized_annual_range' # calculate annual min/max values annual_max = daily_combined_occ_fracs.max_by(&:max).max annual_min = daily_combined_occ_fracs.min_by(&:min).min # normalize threshold to annual min/max - annual_normalized_threshold = annual_min + (annual_max - annual_min) * occupied_percentage_threshold + annual_normalized_threshold = annual_min + ((annual_max - annual_min) * occupied_percentage_threshold) # if vals exceed threshold, set val to 1 occ_status_vals = daily_combined_occ_fracs.map { |day_array| day_array.map { |day_val| day_val >= annual_normalized_threshold ? 1 : 0 } } else # threshold_calc_method == 'value' occ_status_vals = daily_combined_occ_fracs.map { |day_array| day_array.map { |day_val| day_val >= occupied_percentage_threshold ? 1 : 0 } } end - # get unique daily profiles - unique_profiles = occ_status_vals.uniq - profile_days_hash = {} # hash of unique profile => array of day indeces - unique_profiles.each do |day_profile| - days_with_profile = occ_status_vals.each_with_index.filter_map { |day, i| i + 1 if day == day_profile } - profile_days_hash[day_profile] = days_with_profile + # get unique daily profiles for weekdays, saturdays and sundays + wd_profile_days = Hash.new { |h, k| h[k] = [] } + sat_profile_days = Hash.new { |h, k| h[k] = [] } + sun_profile_days = Hash.new { |h, k| h[k] = [] } + + occ_status_vals.each_with_index do |day_profile, i| + day_type = OpenStudio::Date.fromDayOfYear(i + 1, year).dayOfWeek.valueName + if day_type == 'Saturday' + sat_profile_days[day_profile] << (i + 1) + elsif day_type == 'Sunday' + sun_profile_days[day_profile] << (i + 1) + else + wd_profile_days[day_profile] << (i + 1) + end end # create schedule schedule_ruleset = OpenStudio::Model::ScheduleRuleset.new(spaces[0].model) schedule_ruleset.setName(sch_name.to_s) @@ -556,21 +565,24 @@ schedule_ruleset.setSummerDesignDaySchedule(schedule_ruleset.summerDesignDaySchedule) day_sch = schedule_ruleset.summerDesignDaySchedule day_sch.setName("#{sch_name} Summer Design Day") day_sch.addValue(OpenStudio::Time.new(0, 24, 0, 0), 1) - # set most used profile to default day - most_used_profile = profile_days_hash.max_by { |k, v| v.size }.first + # set most used weekday profile to default day + most_used_wd_profile = wd_profile_days.max_by { |k, v| v.size }.first default_day = schedule_ruleset.defaultDaySchedule default_day.setName("#{sch_name} Default") - OpenstudioStandards::Schedules.schedule_day_populate_from_array_of_values(default_day, most_used_profile) + OpenstudioStandards::Schedules.schedule_day_populate_from_array_of_values(default_day, most_used_wd_profile) - # create rules from remaining profiles - remaining_profiles = profile_days_hash.slice(*profile_days_hash.keys.reject { |k| k == most_used_profile }) - remaining_profiles.each do |profile, days_used| - rules = OpenstudioStandards::Schedules.schedule_ruleset_create_rules_from_day_list(schedule_ruleset, days_used) - rules.each { |rule| OpenstudioStandards::Schedules.schedule_day_populate_from_array_of_values(rule.daySchedule, profile) } + # create rules from remaining weekday, saturday and sunday profiles + remaining_wd_profiles = wd_profile_days.slice(*wd_profile_days.keys.reject { |k| k == most_used_wd_profile }) + + [remaining_wd_profiles, sat_profile_days, sun_profile_days].each do |profile_hash| + profile_hash.each do |profile, days_used| + rules = OpenstudioStandards::Schedules.schedule_ruleset_create_rules_from_day_list(schedule_ruleset, days_used) + rules.each { |rule| OpenstudioStandards::Schedules.schedule_day_populate_from_array_of_values(rule.daySchedule, profile) } + end end return schedule_ruleset end @@ -585,12 +597,12 @@ # @param parametric_inputs [Hash] # @param hours_of_operation [Hash] # @param gather_data_only [Boolean] # @return [Hash] def self.space_load_instance_get_parametric_schedule_inputs(space_load_instance, parametric_inputs, hours_of_operation, gather_data_only) - if space_load_instance.class.to_s == 'OpenStudio::Model::People' + if space_load_instance.instance_of?(OpenStudio::Model::People) opt_sch = space_load_instance.numberofPeopleSchedule - elsif space_load_instance.class.to_s == 'OpenStudio::Model::DesignSpecificationOutdoorAir' + elsif space_load_instance.instance_of?(OpenStudio::Model::DesignSpecificationOutdoorAir) opt_sch = space_load_instance.outdoorAirFlowRateFractionSchedule else opt_sch = space_load_instance.schedule end if !opt_sch.is_initialized || !opt_sch.get.to_ScheduleRuleset.is_initialized