Source code for archetypal.template.window_setting

"""archetypal WindowSettings."""

import collections
import logging as lg
from copy import copy
from functools import reduce

from validator_collection import checkers, validators
from validator_collection.errors import EmptyValueError

from archetypal.template.constructions.window_construction import (
    ShadingType,
    WindowConstruction,
    WindowType,
)
from archetypal.template.schedule import UmiSchedule
from archetypal.template.umi_base import UmiBase
from archetypal.utils import log, timeit


[docs]class WindowSetting(UmiBase): """Defines the various window-related properties of a :class:`Zone`. Control natural ventilation, shading and airflow networks and more using this class. This class serves the same role as the ZoneInformation>Windows tab in the UMI TemplateEditor. .. image:: ../images/template/zoneinfo-windows.png Hint: The WindowSetting class implements two constructors that are tailored to the eppy_ scripting language: - :func:`from_construction` and - :func:`from_surface`. .. _eppy : https://eppy.readthedocs.io/en/latest/ """ __slots__ = ( "_operable_area", "_afn_discharge_c", "_afn_temp_setpoint", "_shading_system_setpoint", "_shading_system_transmittance", "_zone_mixing_availability_schedule", "_shading_system_availability_schedule", "_construction", "_afn_window_availability", "_is_shading_system_on", "_is_virtual_partition", "_is_zone_mixing_on", "_shading_system_type", "_type", "_zone_mixing_delta_temperature", "_zone_mixing_flow_rate", "_area", ) def __init__( self, Name, Construction=None, OperableArea=0.8, AfnWindowAvailability=None, AfnDischargeC=0.65, AfnTempSetpoint=20, IsVirtualPartition=False, IsShadingSystemOn=False, ShadingSystemAvailabilitySchedule=None, ShadingSystemSetpoint=180, ShadingSystemTransmittance=0.5, ShadingSystemType=ShadingType.ExteriorShade, Type=WindowType.External, IsZoneMixingOn=False, ZoneMixingAvailabilitySchedule=None, ZoneMixingDeltaTemperature=2, ZoneMixingFlowRate=0.001, area=1, **kwargs, ): """Initialize a WindowSetting using default values. Args: Construction (WindowConstruction): The window construction. OperableArea (float): The operable window area as a ratio of total window area. eg. 0.8 := 80% of the windows area is operable. AfnWindowAvailability (UmiSchedule): The Airflow Network availability schedule. AfnDischargeC (float): Airflow Network Discharge Coefficient. Default = 0.65. AfnTempSetpoint (float): Airflow Network Temperature Setpoint. Default = 20 degreeC. IsVirtualPartition (bool): Virtual Partition. IsShadingSystemOn (bool): Shading is used. Default is False. ShadingSystemAvailabilitySchedule (UmiSchedule): Shading system availability schedule. ShadingSystemSetpoint (float): Shading system setpoint in units of W/m2. Default = 180 W/m2. ShadingSystemTransmittance (float): Shading system transmittance. Default = 0.5. ShadingSystemType (int): Shading System Type. 0 = ExteriorShade, 1 = InteriorShade. Type (int): IsZoneMixingOn (bool): Zone mixing. ZoneMixingAvailabilitySchedule (UmiSchedule): Zone mixing availability schedule. ZoneMixingDeltaTemperature (float): Zone mixing delta ZoneMixingFlowRate (float): Zone mixing flow rate in units of m3/m2. Default = 0.001 m3/m2. **kwargs: other keywords passed to the constructor. """ super(WindowSetting, self).__init__(Name, **kwargs) self.ShadingSystemAvailabilitySchedule = ShadingSystemAvailabilitySchedule self.Construction = Construction self.AfnWindowAvailability = AfnWindowAvailability self.AfnDischargeC = AfnDischargeC self.AfnTempSetpoint = AfnTempSetpoint self.IsShadingSystemOn = IsShadingSystemOn self.IsVirtualPartition = IsVirtualPartition self.IsZoneMixingOn = IsZoneMixingOn self.OperableArea = OperableArea self.ShadingSystemSetpoint = ShadingSystemSetpoint self.ShadingSystemTransmittance = ShadingSystemTransmittance self.ShadingSystemType = ShadingType(ShadingSystemType) self.Type = WindowType(Type) self.ZoneMixingDeltaTemperature = ZoneMixingDeltaTemperature self.ZoneMixingFlowRate = ZoneMixingFlowRate self.ZoneMixingAvailabilitySchedule = ZoneMixingAvailabilitySchedule self.area = area @property def area(self): """Get or set the area of the zone associated to this object [m²].""" return self._area @area.setter def area(self, value): self._area = validators.float(value, minimum=0) @property def OperableArea(self): """Get or set the operable area ratio [-].""" return self._operable_area @OperableArea.setter def OperableArea(self, value): self._operable_area = validators.float(value, minimum=0, maximum=1) @property def AfnDischargeC(self): """Get or set the air flow network discarge coefficient.""" return self._afn_discharge_c @AfnDischargeC.setter def AfnDischargeC(self, value): self._afn_discharge_c = validators.float(value, minimum=0, maximum=1) @property def AfnTempSetpoint(self): """Get or set the air flow network setpoint temperature [degC].""" return self._afn_temp_setpoint @AfnTempSetpoint.setter def AfnTempSetpoint(self, value): self._afn_temp_setpoint = validators.float(value, minimum=-100, maximum=100) @property def AfnWindowAvailability(self): """Get or set the air flow network window availability schedule.""" return self._afn_window_availability @AfnWindowAvailability.setter def AfnWindowAvailability(self, value): if value is not None: assert isinstance(value, UmiSchedule), ( f"Input error with value {value}. AfnWindowAvailability must " f"be an UmiSchedule, not a {type(value)}" ) self._afn_window_availability = value @property def ShadingSystemType(self): """Get or set the shading system type [enum].""" return self._shading_system_type @ShadingSystemType.setter def ShadingSystemType(self, value): if checkers.is_string(value): assert ShadingType[value], ( f"Input value error for '{value}'. " f"Expected one of {tuple(a for a in ShadingType)}" ) self._shading_system_type = ShadingType[value] elif checkers.is_numeric(value): assert ShadingType[value], ( f"Input value error for '{value}'. " f"Expected one of {tuple(a for a in ShadingType)}" ) self._shading_system_type = ShadingType(value) elif isinstance(value, ShadingType): self._shading_system_type = value @property def ShadingSystemSetpoint(self): """Get or set the shading system setpoint [W/m2].""" return self._shading_system_setpoint @ShadingSystemSetpoint.setter def ShadingSystemSetpoint(self, value): self._shading_system_setpoint = validators.float(value, minimum=0) @property def ShadingSystemTransmittance(self): """Get or set the shading system transmittance [-].""" return self._shading_system_transmittance @ShadingSystemTransmittance.setter def ShadingSystemTransmittance(self, value): self._shading_system_transmittance = validators.float( value, minimum=0, maximum=1 ) @property def ShadingSystemAvailabilitySchedule(self): """Get or set the shading system availability schedule.""" return self._shading_system_availability_schedule @ShadingSystemAvailabilitySchedule.setter def ShadingSystemAvailabilitySchedule(self, value): if value is not None: assert isinstance(value, UmiSchedule), ( f"Input error with value {value}. ZoneMixingAvailabilitySchedule must " f"be an UmiSchedule, not a {type(value)}" ) self._shading_system_availability_schedule = value @property def IsShadingSystemOn(self): """Get or set the use of the shading system.""" return self._is_shading_system_on @IsShadingSystemOn.setter def IsShadingSystemOn(self, value): assert isinstance(value, bool), ( f"Input error with value {value}. IsShadingSystemOn must " f"be a boolean, not a {type(value)}" ) self._is_shading_system_on = value @property def ZoneMixingAvailabilitySchedule(self): """Get or set the zone mixing availability schedule.""" return self._zone_mixing_availability_schedule @ZoneMixingAvailabilitySchedule.setter def ZoneMixingAvailabilitySchedule(self, value): if value is not None: assert isinstance(value, UmiSchedule), ( f"Input error with value {value}. ZoneMixingAvailabilitySchedule must " f"be an UmiSchedule, not a {type(value)}" ) self._zone_mixing_availability_schedule = value @property def ZoneMixingDeltaTemperature(self): """Get or set the zone mixing delta temperature.""" return self._zone_mixing_delta_temperature @ZoneMixingDeltaTemperature.setter def ZoneMixingDeltaTemperature(self, value): self._zone_mixing_delta_temperature = validators.float(value, minimum=0) @property def Construction(self): """Get or set the window construction.""" return self._construction @Construction.setter def Construction(self, value): if value is not None: assert isinstance(value, WindowConstruction), ( f"Input error with value {value}. Construction must " f"be an WindowConstruction, not a {type(value)}" ) self._construction = value @property def IsVirtualPartition(self): """Get or set the state of the virtual partition.""" return self._is_virtual_partition @IsVirtualPartition.setter def IsVirtualPartition(self, value): assert isinstance(value, bool), ( f"Input error with value {value}. IsVirtualPartition must " f"be a boolean, not a {type(value)}" ) self._is_virtual_partition = value @property def IsZoneMixingOn(self): """Get or set mixing in zone.""" return self._is_zone_mixing_on @IsZoneMixingOn.setter def IsZoneMixingOn(self, value): assert isinstance(value, bool), ( f"Input error with value {value}. IsZoneMixingOn must " f"be a boolean, not a {type(value)}" ) self._is_zone_mixing_on = value @property def ZoneMixingFlowRate(self): """Get or set the zone mixing flow rate [m3/s].""" return self._zone_mixing_flow_rate @ZoneMixingFlowRate.setter def ZoneMixingFlowRate(self, value): self._zone_mixing_flow_rate = validators.float(value, minimum=0) @property def Type(self): """Get or set the window type [enum].""" return self._type @Type.setter def Type(self, value): if checkers.is_string(value): assert WindowType[value], ( f"Input value error for '{value}'. " f"Expected one of {tuple(a for a in WindowType)}" ) self._type = WindowType[value] elif checkers.is_numeric(value): assert WindowType[value], ( f"Input value error for '{value}'. " f"Expected one of {tuple(a for a in WindowType)}" ) self._type = WindowType(value) elif isinstance(value, WindowType): self._type = value def __add__(self, other): """Combine self and other.""" return self.combine(other) def __repr__(self): """Return a representation of self.""" return super(WindowSetting, self).__repr__() def __str__(self): """Return string representation.""" return repr(self) def __hash__(self): """Return the hash value of self.""" return hash( (self.__class__.__name__, getattr(self, "Name", None), self.DataSource) ) def __eq__(self, other): """Assert self is equivalent to other.""" if not isinstance(other, WindowSetting): return NotImplemented else: return all( [ self.Construction == other.Construction, self.OperableArea == other.OperableArea, self.AfnWindowAvailability == other.AfnWindowAvailability, self.AfnDischargeC == other.AfnDischargeC, self.AfnTempSetpoint == other.AfnTempSetpoint, self.IsVirtualPartition == other.IsVirtualPartition, self.IsShadingSystemOn == other.IsShadingSystemOn, self.ShadingSystemAvailabilitySchedule == other.ShadingSystemAvailabilitySchedule, self.ShadingSystemSetpoint == other.ShadingSystemSetpoint, self.ShadingSystemTransmittance == other.ShadingSystemTransmittance, self.ShadingSystemType == other.ShadingSystemType, self.Type == other.Type, self.IsZoneMixingOn == other.IsZoneMixingOn, self.ZoneMixingAvailabilitySchedule == other.ZoneMixingAvailabilitySchedule, self.ZoneMixingDeltaTemperature == other.ZoneMixingDeltaTemperature, self.ZoneMixingFlowRate == other.ZoneMixingFlowRate, ] )
[docs] @classmethod def generic(cls, Name): """Initialize a generic window with SHGC=0.704, UFactor=2.703, Tvis=0.786. Args: Name (str): Name of the WindowSetting """ construction = WindowConstruction.from_shgc( "SimpleWindow:SINGLE PANE HW WINDOW", u_factor=2.703, solar_heat_gain_coefficient=0.704, visible_transmittance=0.786, ) return WindowSetting(Name, Construction=construction)
[docs] @classmethod def from_construction(cls, Construction, **kwargs): """Make a :class:`WindowSetting` directly from a Construction_ object. .. _Construction : https://bigladdersoftware.com/epx/docs/8-9/input-output-reference/group-surface-construction-elements.html#construction-000 Examples: >>> from archetypal import IDF >>> from archetypal.template.window_setting import WindowSetting >>> # Given an IDF object >>> idf = IDF("idfname.idf") >>> constr = idf.getobject('CONSTRUCTION', >>> 'AEDG-SmOffice 1A Window Fixed') >>> WindowSetting.from_construction( >>> Name='test_window', >>> Construction=constr >>> ) Args: Construction (EpBunch): The construction name for this window. **kwargs: Other keywords passed to the constructor. Returns: (windowSetting): The window setting object. """ name = kwargs.pop("Name", Construction.Name + "_Window") construction = WindowConstruction.from_epbunch(Construction, **kwargs) AfnWindowAvailability = UmiSchedule.constant_schedule() ShadingSystemAvailabilitySchedule = UmiSchedule.constant_schedule() ZoneMixingAvailabilitySchedule = UmiSchedule.constant_schedule() return cls( Name=name, Construction=construction, AfnWindowAvailability=AfnWindowAvailability, ShadingSystemAvailabilitySchedule=ShadingSystemAvailabilitySchedule, ZoneMixingAvailabilitySchedule=ZoneMixingAvailabilitySchedule, **kwargs, )
[docs] @classmethod def from_surface(cls, surface, **kwargs): """Build a WindowSetting object from a FenestrationSurface:Detailed_. This constructor will detect common window constructions and shading devices. Supported Shading and Natural Air flow EnergyPlus objects are: WindowProperty:ShadingControl_, AirflowNetwork:MultiZone:Surface_. Important: If an EnergyPlus object is not supported, eg.: AirflowNetwork:MultiZone:Component:DetailedOpening_, only a warning will be issued in the console for the related object instance and default values will be automatically used. .. _FenestrationSurface:Detailed: https://bigladdersoftware.com/epx/docs/8-9/input-output-reference /group-thermal-zone-description-geometry.html #fenestrationsurfacedetailed .. _WindowProperty:ShadingControl: https://bigladdersoftware.com/epx/docs/8-9/input-output-reference /group-thermal-zone-description-geometry.html #windowpropertyshadingcontrol .. _AirflowNetwork:MultiZone:Surface: https://bigladdersoftware.com/epx/docs/8-9/input-output-reference /group-airflow-network.html#airflownetworkmultizonesurface .. _AirflowNetwork:MultiZone:Component:DetailedOpening: https://bigladdersoftware.com/epx/docs/8-9/input-output-reference /group-airflow-network.html #airflownetworkmultizonecomponentdetailedopening Args: surface (EpBunch): The FenestrationSurface:Detailed_ object. Returns: (WindowSetting): The window setting object. """ if surface.key.upper() == "FENESTRATIONSURFACE:DETAILED": if not surface.Surface_Type.lower() == "window": return # Other surface types (Doors, GlassDoors, etc.) are ignored. construction = surface.get_referenced_object("Construction_Name") if construction is None: construction = surface.theidf.getobject( "CONSTRUCTION", surface.Construction_Name ) construction = WindowConstruction.from_epbunch(construction) shading_control = surface.get_referenced_object("Shading_Control_Name") elif surface.key.upper() == "WINDOW": construction = surface.get_referenced_object("Construction_Name") construction = WindowConstruction.from_epbunch(construction) shading_control = next( iter( surface.getreferingobjs( iddgroups=["Thermal Zones and Surfaces"], fields=[f"Fenestration_Surface_{i}_Name" for i in range(1, 10)], ) ), None, ) elif surface.key.upper() == "DOOR": return # Simply skip doors. else: raise ValueError( f"A window of type {surface.key} is not yet supported. " f"Please contact developers" ) attr = {} if shading_control: # a WindowProperty:ShadingControl_ object can be attached to # this window attr["IsShadingSystemOn"] = True if shading_control["Setpoint"] != "": attr["ShadingSystemSetpoint"] = shading_control["Setpoint"] shade_mat = shading_control.get_referenced_object( "Shading_Device_Material_Name" ) # get shading transmittance if shade_mat: attr["ShadingSystemTransmittance"] = shade_mat["Visible_Transmittance"] # get shading control schedule if shading_control["Shading_Control_Is_Scheduled"].upper() == "YES": name = shading_control["Schedule_Name"] attr["ShadingSystemAvailabilitySchedule"] = UmiSchedule.from_epbunch( surface.theidf.schedules_dict[name.upper()] ) else: # Determine which behavior of control shade_ctrl_type = shading_control["Shading_Control_Type"] if shade_ctrl_type.lower() == "alwaysoff": attr[ "ShadingSystemAvailabilitySchedule" ] = UmiSchedule.constant_schedule(value=0, name="AlwaysOff") elif shade_ctrl_type.lower() == "alwayson": attr[ "ShadingSystemAvailabilitySchedule" ] = UmiSchedule.constant_schedule() else: log( 'Window "{}" uses a window control type that ' 'is not supported: "{}". Reverting to ' '"AlwaysOn"'.format(surface.Name, shade_ctrl_type), lg.WARN, ) attr[ "ShadingSystemAvailabilitySchedule" ] = UmiSchedule.constant_schedule() # get shading type if shading_control["Shading_Type"] != "": mapping = { "InteriorShade": ShadingType(1), "ExteriorShade": ShadingType(0), "ExteriorScreen": ShadingType(0), "InteriorBlind": ShadingType(1), "ExteriorBlind": ShadingType(0), "BetweenGlassShade": ShadingType(0), "BetweenGlassBlind": ShadingType(0), "SwitchableGlazing": ShadingType(0), } attr["ShadingSystemType"] = mapping[shading_control["Shading_Type"]] else: # Set default schedules attr["ShadingSystemAvailabilitySchedule"] = UmiSchedule.constant_schedule() # get airflow network afn = next( iter( surface.getreferingobjs( iddgroups=["Natural Ventilation and Duct Leakage"], fields=["Surface_Name"], ) ), None, ) if afn: attr["OperableArea"] = afn.WindowDoor_Opening_Factor_or_Crack_Factor leak = afn.get_referenced_object("Leakage_Component_Name") name = afn["Venting_Availability_Schedule_Name"] if name != "": attr["AfnWindowAvailability"] = UmiSchedule.from_epbunch( surface.theidf.schedules_dict[name.upper()] ) else: attr["AfnWindowAvailability"] = UmiSchedule.constant_schedule() name = afn["Ventilation_Control_Zone_Temperature_Setpoint_Schedule_Name"] if name != "": attr["AfnTempSetpoint"] = UmiSchedule( Name=name, idf=surface.theidf ).mean else: pass # uses default if ( leak.key.upper() == "AIRFLOWNETWORK:MULTIZONE:SURFACE:EFFECTIVELEAKAGEAREA" ): attr["AfnDischargeC"] = leak["Discharge_Coefficient"] elif ( leak.key.upper() == "AIRFLOWNETWORK:MULTIZONE:COMPONENT:HORIZONTALOPENING" ): log( '"{}" is not fully supported. Reverting to ' 'defaults for object "{}"'.format(leak.key, cls.mro()[0].__name__), lg.WARNING, ) elif leak.key.upper() == "AIRFLOWNETWORK:MULTIZONE:SURFACE:CRACK": log( '"{}" is not fully supported. Rerverting to ' 'defaults for object "{}"'.format(leak.key, cls.mro()[0].__name__), lg.WARNING, ) elif ( leak.key.upper() == "AIRFLOWNETWORK:MULTIZONE:COMPONENT:DETAILEDOPENING" ): log( '"{}" is not fully supported. Rerverting to ' 'defaults for object "{}"'.format(leak.key, cls.mro()[0].__name__), lg.WARNING, ) elif ( leak.key.upper() == "AIRFLOWNETWORK:MULTIZONE:COMPONENT:ZONEEXHAUSTFAN" ): log( '"{}" is not fully supported. Rerverting to ' 'defaults for object "{}"'.format(leak.key, cls.mro()[0].__name__), lg.WARNING, ) elif leak.key.upper() == "AIRFLOWNETWORK:MULTIZONE:COMPONENT:SIMPLEOPENING": log( '"{}" is not fully supported. Rerverting to ' 'defaults for object "{}"'.format(leak.key, cls.mro()[0].__name__), lg.WARNING, ) else: attr["AfnWindowAvailability"] = UmiSchedule.constant_schedule( value=0, Name="AlwaysOff" ) # Todo: Zone Mixing is always off attr["ZoneMixingAvailabilitySchedule"] = UmiSchedule.constant_schedule( value=0, Name="AlwaysOff" ) DataSource = kwargs.pop("DataSource", surface.theidf.name) Category = kwargs.pop("Category", surface.theidf.name) w = cls( Name=surface.Name, Construction=construction, idf=surface.theidf, Category=Category, DataSource=DataSource, **attr, **kwargs, ) return w
@classmethod @timeit def from_zone(cls, zone, **kwargs): """Iterate over the zone subsurfaces and create a window object. If more than one window is created, use reduce to combine them together. Args: zone (Zone): The Zone object from which the WindowSetting is created. Returns: WindowSetting: The WindowSetting object for this zone. """ window_sets = [] for surf in zone.zone_surfaces: # skip internalmass objects since they don't have windows. if surf.key.lower() != "internalmass": for subsurf in surf.subsurfaces: # For each subsurface, create a WindowSetting object # using the `from_surface` constructor. window_sets.append(cls.from_surface(subsurf, **kwargs)) if window_sets: # if one or more window has been created, reduce. Using reduce on # a len==1 list, will simply return the object. return reduce(WindowSetting.combine, window_sets) else: # no window found, probably a core zone, return None. return None
[docs] def combine(self, other, weights=None, allow_duplicates=False): """Append other to self. Return self + other as a new object. Args: other (WindowSetting): The other OpaqueMaterial object weights (list-like, optional): A list-like object of len 2. If None, equal weights are used. Returns: WindowSetting: A new combined object made of self + other. """ # Check if other is None. Simply return self if not other: return self if not self: return other if not isinstance(other, self.__class__): msg = "Cannot combine %s with %s" % ( self.__class__.__name__, other.__class__.__name__, ) raise NotImplementedError(msg) # Check if other is not the same as self if self == other: return self if not weights: log( 'using 1 as weighting factor in "{}" ' "combine.".format(self.__class__.__name__) ) weights = [1.0, 1.0] meta = self._get_predecessors_meta(other) new_attr = dict( Construction=WindowConstruction.combine( self.Construction, other.Construction, weights ), AfnDischargeC=self.float_mean(other, "AfnDischargeC", weights), AfnTempSetpoint=self.float_mean(other, "AfnTempSetpoint", weights), AfnWindowAvailability=UmiSchedule.combine( self.AfnWindowAvailability, other.AfnWindowAvailability, weights ), IsShadingSystemOn=any([self.IsShadingSystemOn, other.IsShadingSystemOn]), IsVirtualPartition=any([self.IsVirtualPartition, other.IsVirtualPartition]), IsZoneMixingOn=any([self.IsZoneMixingOn, other.IsZoneMixingOn]), OperableArea=self.float_mean(other, "OperableArea", weights), ShadingSystemSetpoint=self.float_mean( other, "ShadingSystemSetpoint", weights ), ShadingSystemTransmittance=self.float_mean( other, "ShadingSystemTransmittance", weights ), ShadingSystemType=max(self.ShadingSystemType, other.ShadingSystemType), ZoneMixingDeltaTemperature=self.float_mean( other, "ZoneMixingDeltaTemperature", weights ), ZoneMixingFlowRate=self.float_mean(other, "ZoneMixingFlowRate", weights), ZoneMixingAvailabilitySchedule=UmiSchedule.combine( self.ZoneMixingAvailabilitySchedule, other.ZoneMixingAvailabilitySchedule, weights, ), ShadingSystemAvailabilitySchedule=UmiSchedule.combine( self.ShadingSystemAvailabilitySchedule, other.ShadingSystemAvailabilitySchedule, weights, ), Type=max(self.Type, other.Type), ) new_obj = WindowSetting(**meta, **new_attr) new_obj.predecessors.update(self.predecessors + other.predecessors) return new_obj
[docs] def to_dict(self): """Return WindowSetting dictionary representation.""" self.validate() # Validate object before trying to get json format data_dict = collections.OrderedDict() data_dict["$id"] = str(self.id) data_dict["AfnDischargeC"] = self.AfnDischargeC data_dict["AfnTempSetpoint"] = self.AfnTempSetpoint data_dict["AfnWindowAvailability"] = self.AfnWindowAvailability.to_ref() data_dict["Construction"] = {"$ref": str(self.Construction.id)} data_dict["IsShadingSystemOn"] = self.IsShadingSystemOn data_dict["IsVirtualPartition"] = self.IsVirtualPartition data_dict["IsZoneMixingOn"] = self.IsZoneMixingOn data_dict["OperableArea"] = self.OperableArea data_dict[ "ShadingSystemAvailabilitySchedule" ] = self.ShadingSystemAvailabilitySchedule.to_ref() data_dict["ShadingSystemSetpoint"] = self.ShadingSystemSetpoint data_dict["ShadingSystemTransmittance"] = self.ShadingSystemTransmittance data_dict["ShadingSystemType"] = self.ShadingSystemType.value data_dict["Type"] = self.Type.value data_dict[ "ZoneMixingAvailabilitySchedule" ] = self.ZoneMixingAvailabilitySchedule.to_ref() data_dict["ZoneMixingDeltaTemperature"] = self.ZoneMixingDeltaTemperature data_dict["ZoneMixingFlowRate"] = self.ZoneMixingFlowRate data_dict["Category"] = self.Category data_dict["Comments"] = validators.string(self.Comments, allow_empty=True) data_dict["DataSource"] = self.DataSource data_dict["Name"] = self.Name return data_dict
[docs] @classmethod def from_dict(cls, data, schedules, window_constructions, **kwargs): """Create a ZoneConditioning from a dictionary. Args: data (dict): The python dictionary. schedules (dict): A dictionary of UmiSchedules with their id as keys. window_constructions (dict): A dictionary of WindowConstruction objects with their id as keys. **kwargs: keywords passed to parent constructor. """ data = copy(data) _id = data.pop("$id") afn_availability_schedule = schedules[data.pop("AfnWindowAvailability")["$ref"]] construction = window_constructions[data.pop("Construction")["$ref"]] shading_system_availability_schedule = schedules[ data.pop("ShadingSystemAvailabilitySchedule")["$ref"] ] zone_mixing_availability_schedule = schedules[ data.pop("ZoneMixingAvailabilitySchedule")["$ref"] ] return cls( id=_id, Construction=construction, AfnWindowAvailability=afn_availability_schedule, ShadingSystemAvailabilitySchedule=shading_system_availability_schedule, ZoneMixingAvailabilitySchedule=zone_mixing_availability_schedule, **data, **kwargs, )
[docs] @classmethod def from_ref( cls, ref, building_templates, schedules, window_constructions, **kwargs ): """Initialize :class:`WindowSetting` object from a reference id. Hint: In some cases, the WindowSetting is referenced in the DataStore to the Windows property of a BuildingTemplate (instead of being listed in the WindowSettings list. This is the case in the original BostonTemplateLibrary.json. Args: ref (str): The referenced number in the json library. building_templates (list): List of BuildingTemplates from the datastore. Returns: WindowSetting: The parsed WindowSetting. """ store = next( iter( filter( lambda x: x.get("$id") == ref, [bldg.get("Windows") for bldg in building_templates], ) ) ) w = cls.from_dict(store, schedules, window_constructions, **kwargs) return w
[docs] def validate(self): """Validate object and fill in missing values.""" if not self.AfnWindowAvailability: self.AfnWindowAvailability = UmiSchedule.constant_schedule( value=0, Name="AlwaysOff" ) if not self.ShadingSystemAvailabilitySchedule: self.ShadingSystemAvailabilitySchedule = UmiSchedule.constant_schedule( value=0, Name="AlwaysOff" ) if not self.ZoneMixingAvailabilitySchedule: self.ZoneMixingAvailabilitySchedule = UmiSchedule.constant_schedule( value=0, Name="AlwaysOff" ) return self
[docs] def mapping(self, validate=True): """Get a dict based on the object properties, useful for dict repr. Args: validate (bool): If True, try to validate object before returning the mapping. """ if validate: self.validate() return dict( AfnDischargeC=self.AfnDischargeC, AfnTempSetpoint=self.AfnTempSetpoint, AfnWindowAvailability=self.AfnWindowAvailability, Construction=self.Construction, IsShadingSystemOn=self.IsShadingSystemOn, IsVirtualPartition=self.IsVirtualPartition, IsZoneMixingOn=self.IsZoneMixingOn, OperableArea=self.OperableArea, ShadingSystemAvailabilitySchedule=self.ShadingSystemAvailabilitySchedule, ShadingSystemSetpoint=self.ShadingSystemSetpoint, ShadingSystemTransmittance=self.ShadingSystemTransmittance, ShadingSystemType=self.ShadingSystemType, Type=self.Type, ZoneMixingAvailabilitySchedule=self.ZoneMixingAvailabilitySchedule, ZoneMixingDeltaTemperature=self.ZoneMixingDeltaTemperature, ZoneMixingFlowRate=self.ZoneMixingFlowRate, Category=self.Category, Comments=self.Comments, DataSource=self.DataSource, Name=self.Name, )