Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix(ruleset): Add better default for design days #830

Merged
merged 1 commit into from Feb 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion honeybee_energy/cli/translate.py
Expand Up @@ -7,7 +7,6 @@
import shutil

from ladybug.futil import preparedir
from ladybug.dt import Date
from ladybug.analysisperiod import AnalysisPeriod
from honeybee.model import Model
from honeybee.config import folders as hb_folders
Expand Down
59 changes: 40 additions & 19 deletions honeybee_energy/schedule/ruleset.py
Expand Up @@ -81,7 +81,7 @@ def __init__(self, identifier, default_day_schedule, schedule_rules=None,
self.holiday_schedule = holiday_schedule
self.summer_designday_schedule = summer_designday_schedule
self.winter_designday_schedule = winter_designday_schedule

# initialize properties for extensions and user data
self._properties = ScheduleRulesetProperties(self)
self._user_data = None
Expand Down Expand Up @@ -257,7 +257,7 @@ def is_single_week(self):
for sch in self._schedule_rules]):
return True
return False

@property
def user_data(self):
"""Get or set an optional dictionary for additional meta data for this object.
Expand Down Expand Up @@ -406,7 +406,8 @@ def data_collection(self, timestep=1, start_date=Date(1, 1), end_date=Date(12, 3
else:
unit = 'unknown'
data_type = GenericType('Unknown Data Type', unit)
header = Header(data_type, unit, a_period, metadata={'schedule': self.identifier})
header = Header(data_type, unit, a_period,
metadata={'schedule': self.identifier})
values = self.values(timestep, start_date, end_date, start_dow,
holidays, leap_year)
return HourlyContinuousCollection(header, values)
Expand Down Expand Up @@ -517,13 +518,17 @@ def from_week_daily_values(
following: (1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60).
schedule_type_limit: A ScheduleTypeLimit object that will be used to
validate schedule values against upper/lower limits and assign
units to the schedule values.
units to the schedule values. (Default: None).
summer_designday_values: A list of [24 * timestep] numerical values for
the summer design day. If None, the daily schedule with the highest
average value will be used.
average value will be used unless the schedule_type_limit has a
Temperature unit_type, in which case it will be the daily schedule
with the lowest average value. (Default: None).
winter_designday_values: A list of [24 * timestep] numerical values for
the winter design day. If None, the daily schedule with the lowest
average value will be used.
average value will be used unless the schedule_type_limit has a
Temperature unit_type, in which case it will be the daily schedule
with the highest average value. (Default: None).
"""
# process the rules for the days of the week
schedule_rules = []
Expand Down Expand Up @@ -552,15 +557,19 @@ def from_week_daily_values(

# get ScheduleDay for summer and winter design days
avg_day_vals = [sum(vals) / len(vals) for vals in applied_day_values]
temp_type = True if schedule_type_limit is not None and \
schedule_type_limit.unit_type == 'Temperature' else False
if summer_designday_values is None:
sch_i = avg_day_vals.index(max(avg_day_vals))
sch_i = avg_day_vals.index(min(avg_day_vals)) if temp_type \
else avg_day_vals.index(max(avg_day_vals))
summer = schedule_rules[sch_i]._schedule_day.duplicate()
summer.identifier = '{}_SmrDsn'.format(summer.identifier)
else:
summer = ScheduleDay.from_values_at_timestep(
'{}_SmrDsn'.format(identifier), summer_designday_values, timestep)
if winter_designday_values is None:
sch_i = avg_day_vals.index(min(avg_day_vals))
sch_i = avg_day_vals.index(max(avg_day_vals)) if temp_type \
else avg_day_vals.index(min(avg_day_vals))
winter = schedule_rules[sch_i]._schedule_day.duplicate()
winter.identifier = '{}_WntrDsn'.format(summer.identifier)
else:
Expand Down Expand Up @@ -829,7 +838,7 @@ def to_rules(self, start_date, end_date):
if rule._end_doy > end_doy:
new_rule.end_date = end_date
rules.append(new_rule)
else:
else:
if rule._start_doy <= end_doy:
new_rule1 = rule.duplicate()
new_rule1.end_date = end_doy
Expand Down Expand Up @@ -974,13 +983,16 @@ def to_dict(self, abridged=False):

# optional properties
if len(self._schedule_rules) != 0:
base['schedule_rules'] = [rule.to_dict(True) for rule in self._schedule_rules]
base['schedule_rules'] = \
[rule.to_dict(True) for rule in self._schedule_rules]
if self._holiday_schedule is not None:
base['holiday_schedule'] = self._holiday_schedule.identifier
if self._summer_designday_schedule is not None:
base['summer_designday_schedule'] = self._summer_designday_schedule.identifier
base['summer_designday_schedule'] = \
self._summer_designday_schedule.identifier
if self._winter_designday_schedule is not None:
base['winter_designday_schedule'] = self._winter_designday_schedule.identifier
base['winter_designday_schedule'] = \
self._winter_designday_schedule.identifier

# optional properties that can be abridged
if self._schedule_type_limit is not None:
Expand Down Expand Up @@ -1056,7 +1068,8 @@ def extract_all_from_idf_file(idf_file, import_compact=False):
# extract all of the Schedule:Week objects
week_pattern_1 = re.compile(r"(?i)(Schedule:Week:Daily,[\s\S]*?;)")
week_pattern_2 = re.compile(r"(?i)(Schedule:Week:Compact,[\s\S]*?;)")
week_sch_str = week_pattern_1.findall(file_contents) + week_pattern_2.findall(file_contents)
week_sch_str = week_pattern_1.findall(file_contents) + \
week_pattern_2.findall(file_contents)
week_sch_dict, week_dd_dict = ScheduleRuleset._idf_week_schedule_dictionary(
week_sch_str, day_schedule_dict)
# extract all of the ScheduleTypeLimit objects
Expand Down Expand Up @@ -1200,15 +1213,21 @@ def create_rule_for(apply_to):
holiday_schedule = rule.schedule_day
rules.append(rule)
if "summerdesignday" in field:
rule = ScheduleRule(ScheduleDay("summerdesignday", [0], [Time(0, 0)]))
rule = ScheduleRule(
ScheduleDay("summerdesignday", [0], [Time(0, 0)])
)
summer_designday_schedule = rule.schedule_day
rules.append(rule)
if "winterdesignday" in field:
rule = ScheduleRule(ScheduleDay("winterdesignday", [0], [Time(0, 0)]))
rule = ScheduleRule(
ScheduleDay("winterdesignday", [0], [Time(0, 0)])
)
winter_designday_schedule = rule.schedule_day
rules.append(rule)
if "allotherdays" in field:
rule = ScheduleRule(ScheduleDay("allotherdays", [0], [Time(0, 0)]))
rule = ScheduleRule(
ScheduleDay("allotherdays", [0], [Time(0, 0)])
)
apply_mtx = [rul.week_apply_tuple for rul in schedule_rules]
if not apply_mtx: # situation if allotherdays is the only rule.
rule.apply_all = True
Expand Down Expand Up @@ -1318,10 +1337,12 @@ def average_schedules(identifier, schedules, weights=None, timestep_resolution=1
week_schedules = []
for i, rule_indices in enumerate(unique_rule_sets):
week_identifier = '{}_{}'.format(identifier, i)
week_sched = ScheduleRuleset._get_avg_week(week_identifier, schedules, weights,
timestep_resolution, rule_indices)
week_sched = ScheduleRuleset._get_avg_week(
week_identifier, schedules, weights,
timestep_resolution, rule_indices
)
week_schedules.append(week_sched)
# create a dictionary mapping unique rule index lists to average week schedules
# create a dictionary mapping unique rule indices to average week schedules
rule_set_map = {}
for rule_i, week_sched in zip(unique_rule_sets, week_schedules):
rule_set_map[rule_i] = week_sched
Expand Down
5 changes: 2 additions & 3 deletions honeybee_energy/schedule/typelimit.py
Expand Up @@ -10,7 +10,6 @@
from ladybug.datatype import fraction, temperature, temperaturedelta, power, \
angle, speed, distance, uvalue

import os
import re


Expand All @@ -29,11 +28,11 @@ class ScheduleTypeLimit(object):
upper_limit: An optional number for the upper limit for values in the
schedule. If None or a NoLimit object, there will be no upper limit.
numeric_type: Either one of two strings: 'Continuous' or 'Discrete'. The
latter means that only integers are accepted as schedule values. (Default:
latter means that only integers are accepted as schedule values. (Default:
Continuous).
unit_type: Text for an EnergyPlus unit type, which will be used
to assign units to the values in the schedule. Note that this field
is not used in the actual calculations of EnergyPlus. (Default:
is not used in the actual calculations of EnergyPlus. (Default:
Dimensionless). Choose from the following options:

* Dimensionless
Expand Down