Source code for honeybee_radiance.postprocess.electriclight

"""Functions for post-processing daylight outputs into electric lighting schedules."""
import os

from .annual import generate_default_schedule, _process_input_folder


[docs] def daylight_control_schedules( results_folder, base_schedule=None, ill_setpoint=300, min_power_in=0.3, min_light_out=0.2, off_at_min=False ): """Generate electric lighting schedules from annual daylight results. Such controls will dim the lights according to whether the illuminance values at the sensor locations are at a target illuminance setpoint. The results can be used to account for daylight controls in energy simulations. This function will generate one schedule per sensor grid in the simulation. Each grid should have sensors at the locations in space where daylight dimming sensors are located. Grids with one, two, or more sensors can be used to model setups where fractions of each room are controlled by different sensors. If the sensor grids are distributed over the entire floor of the rooms, the resulting schedules will be idealized, where light dimming has been optimized to supply the minimum illuminance setpoint everywhere in the room. Args: results_folder: The path to the folder containing the annual daylight result files. base_schedule: A list of 8760 fractional values for the lighting schedule representing the usage of lights without any daylight controls. The values of this schedule will be multiplied by the hourly dimming fraction to yield the output lighting schedules. If None, a schedule from 9AM to 5PM on weekdays will be used. (Default: None). ill_setpoint: A number for the illuminance setpoint in lux beyond which electric lights are dimmed if there is sufficient daylight. Some common setpoints are listed below. (Default: 300 lux). * 50 lux - Corridors and hallways. * 150 lux - Computer work spaces (screens provide illumination). * 300 lux - Paper work spaces (reading from surfaces that need illumination). * 500 lux - Retail spaces or museums illuminating merchandise/artifacts. * 1000 lux - Operating rooms and workshops where light is needed for safety. min_power_in: A number between 0 and 1 for the the lowest power the lighting system can dim down to, expressed as a fraction of maximum input power. (Default: 0.3). min_light_out: A number between 0 and 1 the lowest lighting output the lighting system can dim down to, expressed as a fraction of maximum light output. Note that setting this to 1 means lights aren't dimmed at all until the illuminance setpoint is reached. This can be used to approximate manual light-switching behavior when used in conjunction with the off_at_min input below. (Default: 0.2). off_at_min: Boolean to note whether lights should switch off completely when they get to the minimum power input. (Default: False). Returns: A tuple with two values. - schedules: A list of lists where each sub-list represents an electric lighting dimming schedule for a sensor grid. - schedule_ids: A list of text strings for the recommended names of the electric lighting schedules. """ # process the base schedule input into a list of values if base_schedule is None: base_schedule = generate_default_schedule() # get the relevant .ill files grids, sun_up_hours = _process_input_folder(results_folder, '*') sun_up_hours = [int(h) for h in sun_up_hours] # get the dimming fractions for each sensor grid from the .ill files dim_fracts = [] for grid_info in grids: ill_file = os.path.join(results_folder, '%s.ill' % grid_info['full_id']) fract_list = _file_to_dimming_fraction( ill_file, sun_up_hours, ill_setpoint, min_power_in, min_light_out, off_at_min ) dim_fracts.append(fract_list) # create the schedule by combining the base schedule with the dimming fraction schedules, schedule_ids = [], [] for grid_info, dim_fract in zip(grids, dim_fracts): sch_vals = [b_val * d_val for b_val, d_val in zip(base_schedule, dim_fract)] sch_id = '{} Daylight Control'.format(grid_info['full_id']) schedules.append(sch_vals) schedule_ids.append(sch_id) return schedules, schedule_ids
def _file_to_dimming_fraction(ill_file, su_pattern, setpt, m_pow, m_lgt, off_m): """Compute hourly dimming fractions for a given result file.""" # get a base schedule of dimming fractions for the sun-up hours su_values = [0] * len(su_pattern) sensor_count = 0 with open(ill_file) as results: for pt_res in results: sensor_count += 1 for i, val in enumerate(pt_res.split()): su_values[i] += _dimming_from_ill(float(val), setpt, m_pow, m_lgt, off_m) su_values = [val / sensor_count for val in su_values] # account for the hours where the sun is not up dim_fract = [1] * 8760 for val, hr in zip(su_values, su_pattern): dim_fract[hr] = float(val) return dim_fract def _dimming_from_ill(ill_val, ill_setpt, min_pow, min_light, off_at_min): """Compute the dimming fraction from an illuminance value.""" if ill_val > ill_setpt: # dimmed all of the way return 0 if off_at_min else min_pow elif ill_val <= min_light: # not dimmed at all return 1 else: # partially dimmed fract_dim = (ill_setpt - ill_val) / (ill_setpt - min_light) return fract_dim + ((1 - fract_dim) * min_pow)