Source code for honeybee_energy.hvac.heatcool.radiant

# coding=utf-8
"""Low temperature radiant system."""
from __future__ import division

from ._base import _HeatCoolBase

from honeybee._lockable import lockable
from honeybee.typing import float_positive, valid_string


[docs] @lockable class Radiant(_HeatCoolBase): """Low temperature radiant HVAC system. This HVAC template will change the floor and/or ceiling constructions of the Rooms that it is applied to, replacing them with a construction that aligns with the radiant_type property (eg. CeilingMetalPanel). The heating and cooling needs of the space are met with the radiant constructions, which use chilled water at 12.8C (55F) and a hot water temperature somewhere between 32.2C (90F) and 49C (120F) (warmer temperatures are used in colder climate zones). Note that radiant systems are particularly limited in cooling capacity and using them may result in many unmet hours. To reduce unmet hours, one can remove carpets, reduce internal loads, reduce solar and envelope gains during peak times, add thermal mass, and use an expanded comfort range. Args: identifier: Text string for system identifier. Must be < 100 characters and not contain any EnergyPlus special characters. This will be used to identify the object across a model and in the exported IDF. vintage: Text for the vintage of the template system. This will be used to set efficiencies for various pieces of equipment within the system. Choose from the following. * DOE_Ref_Pre_1980 * DOE_Ref_1980_2004 * ASHRAE_2004 * ASHRAE_2007 * ASHRAE_2010 * ASHRAE_2013 * ASHRAE_2016 * ASHRAE_2019 equipment_type: Text for the specific type of the system and equipment. (Default: the first option below) Choose from. * Radiant_Chiller_Boiler * Radiant_Chiller_ASHP * Radiant_Chiller_DHW * Radiant_ACChiller_Boiler * Radiant_ACChiller_ASHP * Radiant_ACChiller_DHW * Radiant_DCW_Boiler * Radiant_DCW_ASHP * Radiant_DCW_DHW unit_ventilators: Boolean to note whether individual zone ventilators are included with the basic heating and cooling system (True) or the system only performs heating and cooling without any ventilation (False). Unlike a DOAS, unit ventilators do not pass the outdoor air through heating or cooling coils to condition it for the space. However, heat recovery effectiveness can be specified, which can temper the air supplied to the zone by the ventilator with exhaust air. All air flow through this ventilator is always balanced for each zone between supply and exhaust and the total flow rate is determined by checking the ventilation and exhaust requirements of the rooms to which the system is assigned. (Default: False). sensible_heat_recovery: A number between 0 and 1 for the effectiveness of sensible heat recovery within unit ventilators if specified. (Default: 0). latent_heat_recovery: A number between 0 and 1 for the effectiveness of latent heat recovery within unit ventilators if specified. (Default: 0). vent_availability_schedule: An optional On/Off discrete schedule to specify when unit ventilators shut off (assuming that the unit_ventilators is True). This will not only reduce heating and cooling load by preventing outdoor air from flowing but will also shut off the fans, which can result in more energy savings when spaces served by the ventilators are completely unoccupied. If None, the unit ventilators will be always on. (Default: None). radiant_type: Text to indicate which faces are thermally active. Note that systems are assumed to be embedded in concrete slabs unless CeilingMetalPanel or FloorWithHardwood is specified. Choose from the following. (Default: Floor). * Floor * Ceiling * FloorWithCarpet * CeilingMetalPanel * FloorWithHardwood switch_over_time: A number for the minimum number of hours for when the system can switch between heating and cooling. Note that this has no effect if the radiant_type is not in a slab. (Default: 24). Properties: * identifier * display_name * vintage * equipment_type * unit_ventilators * sensible_heat_recovery * latent_heat_recovery * vent_availability_schedule * radiant_type * switch_over_time * has_air_loop * has_district_heating * has_district_cooling * balances_exhaust * user_data * properties """ __slots__ = ('_radiant_type', '_switch_over_time') EQUIPMENT_TYPES = ( 'Radiant_Chiller_Boiler', 'Radiant_Chiller_ASHP', 'Radiant_Chiller_DHW', 'Radiant_ACChiller_Boiler', 'Radiant_ACChiller_ASHP', 'Radiant_ACChiller_DHW', 'Radiant_DCW_Boiler', 'Radiant_DCW_ASHP', 'Radiant_DCW_DHW' ) radiant_typeS = ('Floor', 'Ceiling', 'FloorWithCarpet', 'CeilingMetalPanel', 'FloorWithHardwood') def __init__( self, identifier, vintage='ASHRAE_2019', equipment_type=None, unit_ventilators=False, sensible_heat_recovery=0, latent_heat_recovery=0, vent_availability_schedule=None, radiant_type='Floor', switch_over_time=24 ): """Initialize HVACSystem.""" # initialize base HVAC system properties _HeatCoolBase.__init__( self, identifier, vintage, equipment_type, unit_ventilators, sensible_heat_recovery, latent_heat_recovery, vent_availability_schedule ) # set the main features of the HVAC system self.radiant_type = radiant_type self.switch_over_time = switch_over_time @property def radiant_type(self): """Get or set text to indicate the type of radiant system.""" return self._radiant_type @radiant_type.setter def radiant_type(self, value): clean_input = valid_string(value).lower() for key in self.radiant_typeS: if key.lower() == clean_input: value = key break else: raise ValueError( 'radiant_type {} is not recognized.\nChoose from the ' 'following:\n{}'.format(value, self.radiant_typeS)) self._radiant_type = value @property def switch_over_time(self): """Get or set the minimum hours the system can switch between heating/cooling.""" return self._switch_over_time @switch_over_time.setter def switch_over_time(self, value): self._switch_over_time = float_positive(value, 'hvac switch over time')
[docs] @classmethod def from_dict(cls, data): """Create a HVAC object from a dictionary. Args: data: A dictionary in following the format below. .. code-block:: python { "type": "", # text for the class name of the HVAC "identifier": "Classroom1_System", # identifier for the HVAC "display_name": "Standard System", # name for the HVAC "vintage": "ASHRAE_2019", # text for the vintage of the template "equipment_type": "", # text for the HVAC equipment type "unit_ventilators": True, # boolean for unit ventilators "sensible_heat_recovery": 0.75, # sensible heat recovery effectiveness "latent_heat_recovery": 0.7, # latent heat recovery effectiveness "vent_availability_schedule": {}, # Schedule for DOAS availability or None "radiant_type": "CeilingMetalPanel", # type of radiant system "switch_over_time": 24 # number of hours to switch between heating + cooling } """ assert data['type'] == cls.__name__, \ 'Expected {} dictionary. Got {}.'.format(cls.__name__, data['type']) # extract the key features and properties of the HVAC vent_avail = cls._get_schedule_from_dict(data['vent_availability_schedule']) if \ 'vent_availability_schedule' in data and \ data['vent_availability_schedule'] is not None else None erv, sensible, latent = cls._properties_from_dict(data) f_type, sot = cls._radiant_properties_from_dict(data) new_obj = cls( data['identifier'], data['vintage'], data['equipment_type'], erv, sensible, latent, vent_avail, radiant_type=f_type, switch_over_time=sot ) if 'display_name' in data and data['display_name'] is not None: new_obj.display_name = data['display_name'] if 'user_data' in data and data['user_data'] is not None: new_obj.user_data = data['user_data'] return new_obj
[docs] @classmethod def from_dict_abridged(cls, data, schedule_dict): """Create a HVAC object from an abridged dictionary. Args: data: An abridged dictionary in following the format below. schedule_dict: A dictionary with schedule identifiers as keys and honeybee schedule objects as values (either ScheduleRuleset or ScheduleFixedInterval). These will be used to assign the schedules to the Setpoint object. .. code-block:: python { "type": "", # text for the class name of the HVAC "identifier": "Classroom1_System", # identifier for the HVAC "display_name": "Standard System", # name for the HVAC "vintage": "ASHRAE_2019", # text for the vintage of the template "equipment_type": "", # text for the HVAC equipment type "unit_ventilators": True, # boolean for unit ventilators "sensible_heat_recovery": 0.75, # sensible heat recovery effectiveness "latent_heat_recovery": 0.7, # latent heat recovery effectiveness "vent_availability_schedule": "", # Schedule id for ventilation availability "radiant_type": "CeilingMetalPanel", # type of radiant system "switch_over_time": 24 # number of hours to switch between heating + cooling } """ assert cls.__name__ in data['type'], \ 'Expected {} dictionary. Got {}.'.format(cls.__name__, data['type']) # extract the schedule vent_avail = None if 'vent_availability_schedule' in data and \ data['vent_availability_schedule'] is not None: try: vent_avail = schedule_dict[data['vent_availability_schedule']] except KeyError as e: raise ValueError('Failed to find {} in the schedule_dict.'.format(e)) erv, sensible, latent = cls._properties_from_dict(data) f_type, sot = cls._radiant_properties_from_dict(data) new_obj = cls( data['identifier'], data['vintage'], data['equipment_type'], erv, sensible, latent, vent_avail, radiant_type=f_type, switch_over_time=sot ) if 'display_name' in data and data['display_name'] is not None: new_obj.display_name = data['display_name'] if 'user_data' in data and data['user_data'] is not None: new_obj.user_data = data['user_data'] return new_obj
[docs] def to_dict(self, abridged=False): """Radiant system dictionary representation. Args: abridged: Boolean to note whether the full dictionary describing the object should be returned (False) or just an abridged version (True). This input currently has no effect but may eventually have one if schedule-type properties are exposed on this template. """ base = {'type': self.__class__.__name__} base['identifier'] = self.identifier base['vintage'] = self.vintage base['equipment_type'] = self.equipment_type base['radiant_type'] = self.radiant_type base['switch_over_time'] = self.switch_over_time if self.unit_ventilators: base['unit_ventilators'] = self.unit_ventilators if self.sensible_heat_recovery != 0: base['sensible_heat_recovery'] = self.sensible_heat_recovery if self.latent_heat_recovery != 0: base['latent_heat_recovery'] = self.latent_heat_recovery if self.vent_availability_schedule is not None: base['vent_availability_schedule'] = \ self.vent_availability_schedule.identifier if \ abridged else self.vent_availability_schedule.to_dict() if self._display_name is not None: base['display_name'] = self.display_name if self._user_data is not None: base['user_data'] = self.user_data return base
@staticmethod def _radiant_properties_from_dict(data): """Extract basic radiant properties from a dictionary and assign defaults.""" sot = data['switch_over_time'] if 'switch_over_time' in data else 24 rad_type = data['radiant_type'] if 'radiant_type' in data and \ data['radiant_type'] is not None else 'Floor' return rad_type, sot def __copy__(self): new_obj = self.__class__( self._identifier, self._vintage, self._equipment_type, self._unit_ventilators, self._sensible_heat_recovery, self._latent_heat_recovery, self._vent_availability_schedule, self._radiant_type, self._switch_over_time ) new_obj._display_name = self._display_name new_obj._user_data = None if self._user_data is None else self._user_data.copy() return new_obj def __key(self): """A tuple based on the object properties, useful for hashing.""" return ( self._identifier, self._vintage, self._equipment_type, self._unit_ventilators, self._sensible_heat_recovery, self._latent_heat_recovery, hash(self._vent_availability_schedule), self._radiant_type, self._switch_over_time ) def __hash__(self): return hash(self.__key()) def __eq__(self, other): return isinstance(other, self.__class__) and self.__key() == other.__key() def __ne__(self, other): return not self.__eq__(other)