Source code for dragonfly_doe2.properties.model

# coding=utf-8
"""Model DOE-2 Properties."""
from honeybee_doe2.grouping import _grouped_floor_boundary


[docs] class ModelDoe2Properties(object): """DOE-2 Properties for Dragonfly Model. Args: host: A dragonfly_core Model object that hosts these properties. Properties: * host """ def __init__(self, host): """Initialize ModelDoe2Properties.""" self._host = host @property def host(self): """Get the Model object hosting these properties.""" return self._host
[docs] def check_for_extension(self, raise_exception=True, detailed=False): """Check that the Model is valid for DOE-2 simulation. This process includes all relevant dragonfly-core checks as well as checks that apply only for DOE-2. Args: raise_exception: Boolean to note whether a ValueError should be raised if any errors are found. If False, this method will simply return a text string with all errors that were found. (Default: True). detailed: Boolean for whether the returned object is a detailed list of dicts with error info or a string with a message. (Default: False). Returns: A text string with all errors that were found or a list if detailed is True. This string (or list) will be empty if no errors were found. """ # set up defaults to ensure the method runs correctly detailed = False if raise_exception else detailed msgs = [] tol = self.host.tolerance ang_tol = self.host.angle_tolerance # perform checks for duplicate identifiers, which might mess with other checks msgs.append(self.host.check_all_duplicate_identifiers(False, detailed)) # perform checks for key dragonfly model schema rules msgs.append(self.host.check_degenerate_room_2ds(tol, False, detailed)) msgs.append(self.host.check_self_intersecting_room_2ds(tol, False, detailed)) msgs.append(self.host.check_plenum_depths(tol, False, detailed)) msgs.append(self.host.check_window_parameters_valid(tol, False, detailed)) msgs.append(self.host.check_no_room2d_overlaps(tol, False, detailed)) msgs.append(self.host.check_collisions_between_stories(tol, False, detailed)) msgs.append(self.host.check_roofs_above_rooms(tol, False, detailed)) msgs.append(self.host.check_room2d_floor_heights_valid(False, detailed)) msgs.append(self.host.check_missing_adjacencies(False, detailed)) msgs.append(self.host.check_all_room3d(tol, ang_tol, False, detailed)) # perform checks that are specific to DOE-2 msgs.append(self.check_room_2d_floor_plate_vertex_count(False, detailed)) msgs.append(self.check_no_room_2d_floor_plate_holes(False, detailed)) msgs.append(self.check_no_story_courtyards(tol, False, detailed)) # output a final report of errors or raise an exception full_msgs = [msg for msg in msgs if msg] if detailed: return [m for msg in full_msgs for m in msg] full_msg = '\n'.join(full_msgs) if raise_exception and len(full_msgs) != 0: raise ValueError(full_msg) return full_msg
[docs] def check_all(self, raise_exception=True, detailed=False): """Check all of the aspects of the Model DOE-2 properties. Args: raise_exception: Boolean to note whether a ValueError should be raised if any errors are found. If False, this method will simply return a text string with all errors that were found. detailed: Boolean for whether the returned object is a detailed list of dicts with error info or a string with a message. (Default: False). Returns: A text string with all errors that were found or a list if detailed is True. This string (or list) will be empty if no errors were found. """ # set up defaults to ensure the method runs correctly detailed = False if raise_exception else detailed msgs = [] # perform checks for specific energy simulation rules msgs.append(self.check_room_2d_floor_plate_vertex_count(False, detailed)) # output a final report of errors or raise an exception full_msgs = [msg for msg in msgs if msg] if detailed: return [m for msg in full_msgs for m in msg] full_msg = '\n'.join(full_msgs) if raise_exception and len(full_msgs) != 0: raise ValueError(full_msg) return full_msg
[docs] def check_room_2d_floor_plate_vertex_count( self, raise_exception=True, detailed=False): """Check whether any Room2Ds floor geometry exceeds the maximum vertex count. The DOE-2 engine currently does not support such rooms and limits the total number of vertices to 120. Args: raise_exception: If True, a ValueError will be raised if the Room2D floor plate exceeds the maximum number of vertices supported by DOE-2. (Default: True). detailed: Boolean for whether the returned object is a detailed list of dicts with error info or a string with a message. (Default: False). Returns: A string with the message or a list with a dictionary if detailed is True. """ detailed = False if raise_exception else detailed msgs = [] for room in self.host.room_2ds: msg = room.properties.doe2.check_floor_plate_vertex_count(False, detailed) if detailed: msgs.extend(msg) elif msg != '': msgs.append(msg) if detailed: return msgs full_msg = '\n'.join(msgs) if raise_exception and len(msgs) != 0: raise ValueError(full_msg) return full_msg
[docs] def check_no_room_2d_floor_plate_holes(self, raise_exception=True, detailed=False): """Check whether any Room2D floor geometry has holes. EQuest currently has no way to represent such rooms so, if the issue is not addressed, the hole will simply be removed as part of the process of exporting to an INP file. Args: raise_exception: If True, a ValueError will be raised if the Room2D floor plate has one or more holes. (Default: True). detailed: Boolean for whether the returned object is a detailed list of dicts with error info or a string with a message. (Default: False). Returns: A string with the message or a list with a dictionary if detailed is True. """ detailed = False if raise_exception else detailed msgs = [] for room in self.host.room_2ds: msg = room.properties.doe2.check_no_floor_plate_holes(False, detailed) if detailed: msgs.extend(msg) elif msg != '': msgs.append(msg) if detailed: return msgs full_msg = '\n'.join(msgs) if raise_exception and len(msgs) != 0: raise ValueError(full_msg) return full_msg
[docs] def check_no_story_courtyards( self, tolerance=None, raise_exception=True, detailed=False): """Check that Story floor plates do not contain courtyards. EQuest currently has no way to represent such courtyards so, if the issue is not addressed, the courtyards will simply be removed as part of the process of exporting to an INP file. Args: tolerance: The tolerance to be used when joining the Room2D floor plates together into a Story floor plate. If None, the Model tolerance will be used. (Default: None). raise_exception: Boolean to note whether a ValueError should be raised if the story contains a courtyard. (Default: True). detailed: Boolean for whether the returned object is a detailed list of dicts with error info or a string with a message. (Default: False). Returns: A string with the message or a list with a dictionary if detailed is True. """ tolerance = self.host.tolerance if tolerance is None else tolerance story_msgs = [] for bldg in self.host.buildings: for story in bldg.unique_stories: floor_geos = [room.floor_geometry for room in story.room_2ds] joined_geos = _grouped_floor_boundary(floor_geos, tolerance) if any(geo.has_holes for geo in joined_geos): c_count = max(len(geo.holes) for geo in joined_geos if geo.has_holes) hole_msg = 'a courtyard' if c_count == 1 \ else '{} courtyards'.format(c_count) msg = 'The geometry of Story "{}" contains {}, which eQuest ' \ 'cannot represent.'.format(story.display_name, hole_msg) if detailed: msg = { 'type': 'ValidationError', 'code': '030103', 'error_type': 'Story Floor Plate Contains Courtyards', 'extension_type': 'DOE2', 'element_type': 'Room2D', 'element_id': [r.identifier for r in story.room_2ds], 'element_name': [r.display_name for r in story.room_2ds], 'message': msg } story_msgs.append(msg) if detailed: return story_msgs if story_msgs != []: msg = 'The following Stories have courtyards in their floor plates' \ ':\n{}'.format('\n'.join(story_msgs)) if raise_exception: raise ValueError(msg) return msg return ''
[docs] def to_dict(self): """Return Model DOE-2 properties as a dictionary.""" return {'doe2': {'type': 'ModelDoe2Properties'}}
[docs] def apply_properties_from_dict(self, data): """Apply the DOE-2 properties of a dictionary to the host Model of this object. Args: data: A dictionary representation of an entire dragonfly-core Model. Note that this dictionary must have ModelDoe2Properties in order for this method to successfully apply the DOE-2 properties. """ assert 'doe2' in data['properties'], \ 'Dictionary possesses no ModelDoe2Properties.' room_doe2_dicts = [] if 'buildings' in data and data['buildings'] is not None: for b_dict in data['buildings']: if 'unique_stories' in b_dict and b_dict['unique_stories'] is not None: for story_dict in b_dict['unique_stories']: for room_dict in story_dict['room_2ds']: try: room_doe2_dicts.append(room_dict['properties']['doe2']) except KeyError: room_doe2_dicts.append(None) if len(room_doe2_dicts) != 0: for room, r_dict in zip(self.host.room_2ds, room_doe2_dicts): if r_dict is not None: room.properties.doe2.apply_properties_from_dict(r_dict)
[docs] def ToString(self): return self.__repr__()
def __repr__(self): return 'Model DOE2 Properties: [host: {}]'.format(self.host.display_name)