def test_group_by_orientation(): """Test the group_by_orientation method.""" pts_1 = (Point3D(0, 0), Point3D(15, 0), Point3D(10, 5), Point3D(5, 5)) pts_2 = (Point3D(15, 0), Point3D(15, 15), Point3D(10, 10), Point3D(10, 5)) pts_3 = (Point3D(0, 15), Point3D(5, 10), Point3D(10, 10), Point3D(15, 15)) pts_4 = (Point3D(0, 0), Point3D(5, 5), Point3D(5, 10), Point3D(0, 15)) pts_5 = (Point3D(5, 5), Point3D(10, 5), Point3D(10, 10), Point3D(5, 10)) pf_1 = Polyface3D.from_offset_face(Face3D(pts_1), 3) pf_2 = Polyface3D.from_offset_face(Face3D(pts_2), 3) pf_3 = Polyface3D.from_offset_face(Face3D(pts_3), 3) pf_4 = Polyface3D.from_offset_face(Face3D(pts_4), 3) pf_5 = Polyface3D.from_offset_face(Face3D(pts_5), 3) room_1 = Room.from_polyface3d('Zone1', pf_1) room_2 = Room.from_polyface3d('Zone2', pf_2) room_3 = Room.from_polyface3d('Zone3', pf_3) room_4 = Room.from_polyface3d('Zone4', pf_4) room_5 = Room.from_polyface3d('Zone5', pf_5) rooms = [room_1, room_2, room_3, room_4, room_5] adj_info = Room.solve_adjacency(rooms, 0.01) grouped_rooms, core_rooms, orientations = Room.group_by_orientation(rooms) assert len(grouped_rooms) == 4 assert len(core_rooms) == 1 assert orientations == [0.0, 90.0, 180.0, 270.0]
def test_compute_bounding_box_extents_complex(): """Test the bounding box extents of ladybug_geometry.""" # South Room 1: 21 x 10.5 x 3 szone1 = Face3D( [Point3D(0, 0), Point3D(21, 0), Point3D(21, 10.5), Point3D(0, 10.5)]) sroom1 = Room.from_polyface3d('SouthRoom1', Polyface3D.from_offset_face(szone1, 3)) # North Room 1: 21 x 10.5 x 3 nzone1 = Face3D( [Point3D(0, 10.5), Point3D(21, 10.5), Point3D(21, 21), Point3D(0, 21)]) nroom1 = Room.from_polyface3d('NorthRoom1', Polyface3D.from_offset_face(nzone1, 3)) # South Room 2: 21 x 10.5 x 3 szone2 = Face3D([ Point3D(0, 0, 3), Point3D(21, 0, 3), Point3D(21, 10.5, 3), Point3D(0, 10.5, 3) ]) sroom2 = Room.from_polyface3d('SouthRoom2', Polyface3D.from_offset_face(szone2, 3)) # North Room 2: 21 x 10.5 x 3 nzone2 = Face3D([ Point3D(0, 10.5, 3), Point3D(21, 10.5, 3), Point3D(21, 21, 3), Point3D(0, 21, 3) ]) nroom2 = Room.from_polyface3d('NorthRoom2', Polyface3D.from_offset_face(nzone2, 3)) rooms = [sroom1, nroom1, sroom2, nroom2] model = Model('Four_Zone_Simple', rooms) # Rotate the buildings theta = 30.0 model.rotate_xy(theta, rooms[0].geometry.vertices[-1]) geoms = [room.geometry for room in model.rooms] xx, yy, zz = bounding_box_extents(geoms, math.radians(theta)) assert xx == pytest.approx(21, abs=1e-10) assert yy == pytest.approx(21, abs=1e-10) assert zz == pytest.approx(6, abs=1e-10)
def test_polyface3d_init_from_offset_face(): """Test the initalization of Poyface3D from_offset_face.""" face = Face3D.from_rectangle(2, 2) polyface = Polyface3D.from_offset_face(face, 2) assert len(polyface.vertices) == 8 assert len(polyface.face_indices) == 6 assert len(polyface.faces) == 6 assert len(polyface.edge_indices) == 12 assert len(polyface.edges) == 12 assert len(polyface.naked_edges) == 0 assert len(polyface.non_manifold_edges) == 0 assert len(polyface.internal_edges) == 12 assert polyface.area == 24 assert polyface.volume == 8 assert polyface.is_solid for f in polyface.faces: assert f.is_clockwise is False for e in polyface.edges: assert e.length == 2 assert polyface.faces[0].normal.z == pytest.approx(-1, rel=1e-3) assert polyface.faces[-1].normal.z == pytest.approx(1, rel=1e-3) for face in polyface.faces: assert not face.is_clockwise
def test_polyface3d_to_from_dict_hole(): """Test the to/from dict of Polyface3D objects with a hole.""" bound_pts = [Point3D(0, 0), Point3D(3, 0), Point3D(3, 3), Point3D(0, 3)] hole_pts = [Point3D(1, 1), Point3D(2, 1), Point3D(2, 2), Point3D(1, 2)] face = Face3D(bound_pts, None, [hole_pts]) polyface = Polyface3D.from_offset_face(face, 1) polyface_dict = polyface.to_dict() new_polyface = Polyface3D.from_dict(polyface_dict) assert len(new_polyface.vertices) == 16 assert len(new_polyface.face_indices) == 10 assert len(new_polyface.faces) == 10 assert len(new_polyface.edge_indices) == 24 assert len(new_polyface.edges) == 24 assert len(new_polyface.naked_edges) == 0 assert len(new_polyface.non_manifold_edges) == 0 assert len(new_polyface.internal_edges) == 24 assert new_polyface.area == pytest.approx(32, rel=1e-3) assert new_polyface.volume == pytest.approx(8, rel=1e-3) assert new_polyface.is_solid assert new_polyface.faces[0].normal.z == pytest.approx(-1, rel=1e-3) assert new_polyface.faces[-1].normal.z == pytest.approx(1, rel=1e-3) assert new_polyface.faces[0].has_holes assert new_polyface.faces[-1].has_holes for face in polyface.faces: assert not face.is_clockwise
def test_intersect_line_ray(): """Test the Polyface3D intersect_line_ray method.""" pts = (Point3D(0, 0, 2), Point3D(2, 0, 2), Point3D(2, 1, 2), Point3D(1, 1, 2), Point3D(1, 2, 2), Point3D(0, 2, 2)) plane = Plane(Vector3D(0, 0, 1), Point3D(0, 0, 2)) face = Face3D(pts, plane) polyface = Polyface3D.from_offset_face(face, 1) ray_1 = Ray3D(Point3D(0.5, 0.5, 0), Vector3D(0, 0, 1)) ray_2 = Ray3D(Point3D(0.5, 0.5, 0), Vector3D(0, 0, -1)) ray_3 = Ray3D(Point3D(1.5, 1.5, 0), Vector3D(0, 0, 1)) ray_4 = Ray3D(Point3D(-1, -1, 0), Vector3D(0, 0, 1)) line_1 = LineSegment3D(Point3D(0.5, 0.5, 0), Vector3D(0, 0, 3)) line_2 = LineSegment3D(Point3D(0.5, 0.5, 0), Vector3D(0, 0, 1)) assert polyface.does_intersect_line_ray_exist(ray_1) is True assert polyface.does_intersect_line_ray_exist(ray_2) is False assert polyface.does_intersect_line_ray_exist(ray_3) is False assert polyface.does_intersect_line_ray_exist(ray_4) is False assert polyface.does_intersect_line_ray_exist(line_1) is True assert polyface.does_intersect_line_ray_exist(line_2) is False assert polyface.intersect_line_ray(ray_1) == [ Point3D(0.5, 0.5, 2), Point3D(0.5, 0.5, 3) ] assert polyface.intersect_line_ray(ray_2) == [] assert polyface.intersect_line_ray(ray_3) == [] assert polyface.intersect_line_ray(ray_4) == [] assert polyface.intersect_line_ray(line_1) == [ Point3D(0.5, 0.5, 2), Point3D(0.5, 0.5, 3) ] assert polyface.intersect_line_ray(line_2) == []
def test_polyface3d_init_from_polyface(): """Test the initalization of room from a Poyface3D.""" bound_pts = [Point3D(0, 0), Point3D(3, 0), Point3D(3, 3), Point3D(0, 3)] hole_pts = [ Point3D(1, 1, 0), Point3D(2, 1, 0), Point3D(2, 2, 0), Point3D(1, 2, 0) ] face = Face3D(bound_pts, None, [hole_pts]) polyface = Polyface3D.from_offset_face(face, 3) room = Room.from_polyface3d('Donut Zone', polyface) assert room.name == 'DonutZone' assert room.display_name == 'Donut Zone' assert isinstance(room.geometry, Polyface3D) assert len(room.geometry.vertices) == 16 assert len(room) == 10 assert room.center == Point3D(1.5, 1.5, 1.5) assert room.volume == 24 assert room.floor_area == 8 assert room.exposed_area == 56 assert room.exterior_wall_area == 48 assert room.exterior_aperture_area == 0 assert room.average_floor_height == 0 assert not room.has_parent assert room.check_solid(0.01, 1)
def test_envelope_components_by_type(): zone_pts = Face3D([ Point3D(0, 0, 0), Point3D(20, 0, 0), Point3D(20, 10, 0), Point3D(0, 10, 0) ]) room = Room.from_polyface3d('SouthRoom', Polyface3D.from_offset_face(zone_pts, 3)) door_pts = [ Point3D(2, 10, 0.01), Point3D(4, 10, 0.01), Point3D(4, 10, 2.50), Point3D(2, 10, 2.50) ] door = Door('FrontDoor', Face3D(door_pts)) room[3].add_door(door) # Door to north face room[1].apertures_by_ratio(0.3) # Window on south face ext_faces, int_faces = room.properties.energy.envelope_components_by_type() walls, roofs, floors, apertures, doors = ext_faces assert len(walls) == 4 assert len(roofs) == 1 assert len(floors) == 0 assert len(apertures) == 1 assert len(doors) == 1 for types in int_faces: assert len(types) == 0
def model_complete_office_floor(directory): pts_1 = [Point3D(0, 0), Point3D(30, 0), Point3D(20, 10), Point3D(10, 10)] pts_2 = [Point3D(0, 0), Point3D(10, 10), Point3D(10, 20), Point3D(0, 30)] pts_3 = [Point3D(10, 20), Point3D(20, 20), Point3D(30, 30), Point3D(0, 30)] pts_4 = [Point3D(30, 0), Point3D(30, 30), Point3D(20, 20), Point3D(20, 10)] verts = [pts_1, pts_2, pts_3, pts_4] rooms = [] for i, f_vert in enumerate(verts): pface = Polyface3D.from_offset_face(Face3D(f_vert), 3) room = Room.from_polyface3d('PerimeterRoom{}'.format(i), pface) room.properties.energy.program_type = prog_type_lib.office_program room.properties.energy.add_default_ideal_air() rooms.append(room) rooms.append(Room.from_box('CoreRoom', 10, 10, 3, origin=Point3D(10, 10))) adj_info = Room.solve_adjacency(rooms, 0.01) for face_pair in adj_info['adjacent_faces']: face_pair[0].type = face_types.air_boundary face_pair[1].type = face_types.air_boundary for room in rooms: for face in room: if isinstance(face.type, (Floor, RoofCeiling)): face.boundary_condition = boundary_conditions.adiabatic model = Model('Core_Perimeter_Office_Floor', rooms) dest_file = os.path.join(directory, 'model_complete_office_floor.json') with open(dest_file, 'w') as fp: json.dump(model.to_dict(), fp, indent=4)
def test_to_dict_air_walls(): """Test the Model to_dict method with a multi-zone house.""" pts_1 = [Point3D(0, 0), Point3D(30, 0), Point3D(20, 10), Point3D(10, 10)] pts_2 = [Point3D(0, 0), Point3D(10, 10), Point3D(10, 20), Point3D(0, 30)] pts_3 = [Point3D(10, 20), Point3D(20, 20), Point3D(30, 30), Point3D(0, 30)] pts_4 = [Point3D(30, 0), Point3D(30, 30), Point3D(20, 20), Point3D(20, 10)] verts = [pts_1, pts_2, pts_3, pts_4] rooms = [] for i, f_vert in enumerate(verts): pface = Polyface3D.from_offset_face(Face3D(f_vert), 3) room = Room.from_polyface3d('PerimeterRoom{}'.format(i), pface) room.properties.energy.program_type = office_program room.properties.energy.add_default_ideal_air() rooms.append(room) rooms.append(Room.from_box('CoreRoom', 10, 10, 3, origin=Point3D(10, 10))) adj_info = Room.solve_adjacency(rooms, 0.01) for face_pair in adj_info['adjacent_faces']: face_pair[0].type = face_types.air_boundary face_pair[1].type = face_types.air_boundary model = Model('CorePerimeterOfficeFloor', rooms) model_dict = model.to_dict() assert model_dict['rooms'][-1]['faces'][1]['face_type'] == 'AirBoundary' new_model = Model.from_dict(model_dict) air_face_type = new_model.rooms[-1].faces[1] assert air_face_type.type == face_types.air_boundary assert isinstance(air_face_type.properties.energy.construction, AirBoundaryConstruction) model_idf_str = model.to.idf(model) assert model_idf_str.count('Construction:AirBoundary') == 1 assert model_idf_str.count('ZoneMixing') == 16
def test_afn_plenum_zone(): """Test case where no infiltration load exists.""" zone_pts = Face3D( [Point3D(0, 0), Point3D(20, 0), Point3D(20, 10), Point3D(0, 10)]) room = Room.from_polyface3d('PlenumRoom', Polyface3D.from_offset_face(zone_pts, 1)) room.properties.energy.program_type = prog_type_lib.plenum_program # Make model model = Model('PlenumSimple', [room]) # generate afn, w/ average leakage afn.generate(model.rooms, leakage_type='Medium', use_room_infiltration=True) faces = model.faces # check ext wall crack = faces[1].properties.energy.vent_crack chk_cof = CRACK_TEMPLATE_DATA['external_medium_cracks']['wall_flow_cof'] chk_exp = CRACK_TEMPLATE_DATA['external_medium_cracks']['wall_flow_exp'] assert crack.flow_coefficient == pytest.approx(chk_cof * faces[1].area, abs=1e-10) assert crack.flow_exponent == pytest.approx(chk_exp, abs=1e-10) # check roof crack = faces[5].properties.energy.vent_crack chk_cof = CRACK_TEMPLATE_DATA['external_medium_cracks']['roof_flow_cof'] chk_exp = CRACK_TEMPLATE_DATA['external_medium_cracks']['roof_flow_exp'] assert crack.flow_coefficient == pytest.approx(chk_cof * faces[5].area, abs=1e-10) assert crack.flow_exponent == pytest.approx(chk_exp, abs=1e-10) # generate afn, w/ tight leakage afn.generate(model.rooms, leakage_type='Excellent', use_room_infiltration=False) faces = model.faces # check ext wall crack = faces[1].properties.energy.vent_crack chk_cof = CRACK_TEMPLATE_DATA['external_excellent_cracks']['wall_flow_cof'] chk_exp = CRACK_TEMPLATE_DATA['external_excellent_cracks']['wall_flow_exp'] assert crack.flow_coefficient == pytest.approx(chk_cof * faces[1].area, abs=1e-10) assert crack.flow_exponent == pytest.approx(chk_exp, abs=1e-10) # check roof crack = faces[5].properties.energy.vent_crack chk_cof = CRACK_TEMPLATE_DATA['external_excellent_cracks']['roof_flow_cof'] chk_exp = CRACK_TEMPLATE_DATA['external_excellent_cracks']['roof_flow_exp'] assert crack.flow_coefficient == pytest.approx(chk_cof * faces[5].area, abs=1e-10) assert crack.flow_exponent == pytest.approx(chk_exp, abs=1e-10)
def model_complete_holes(directory): bound_pts = [Point3D(0, 0), Point3D(9, 0), Point3D(9, 9), Point3D(0, 9)] hole_pts = [ Point3D(3, 3, 0), Point3D(6, 3, 0), Point3D(6, 6, 0), Point3D(3, 6, 0) ] face = Face3D(bound_pts, None, [hole_pts]) polyface = Polyface3D.from_offset_face(face, 3) room = Room.from_polyface3d('DonutZone', polyface) ap_bound_pts = [ Point3D(0.5, 0, 0.5), Point3D(2.5, 0, 0.5), Point3D(2.5, 0, 2.5), Point3D(0.5, 0, 2.5) ] ap_hole_pts = [ Point3D(1, 0, 1), Point3D(2, 0, 1), Point3D(2, 0, 2), Point3D(1, 0, 2) ] ap_face = Face3D(ap_bound_pts, None, [ap_hole_pts]) ap = Aperture('HoleAperture', ap_face) for face in room.faces: if face.geometry.is_sub_face(ap_face, 0.01, 1.0): face.add_aperture(ap) shd_bound_pts = [ Point3D(0, 0, 6), Point3D(9, 0, 6), Point3D(9, 9, 6), Point3D(0, 9, 6) ] shd_hole_pts1 = [ Point3D(2, 2, 6), Point3D(4, 2, 6), Point3D(4, 4, 6), Point3D(2, 4, 6) ] shd_hole_pts2 = [ Point3D(5, 5, 6), Point3D(7, 5, 6), Point3D(7, 7, 6), Point3D(5, 7, 6) ] s_face = Face3D(shd_bound_pts, None, [shd_hole_pts1, shd_hole_pts2]) shd = Shade('Canopy', s_face) model = Model('Donut_Building', [room], orphaned_shades=[shd]) dest_file = os.path.join(directory, 'model_complete_holes.json') with open(dest_file, 'w') as fp: json.dump(model.to_dict(), fp, indent=4)
def test_afn_single_zone_delta_pressure(): """Test adding afn to single zone with custome delta pressure.""" zone_pts = Face3D( [Point3D(0, 0), Point3D(20, 0), Point3D(20, 10), Point3D(0, 10)]) room = Room.from_polyface3d('SouthRoom', Polyface3D.from_offset_face(zone_pts, 3)) # Make model room.properties.energy.program_type = prog_type_lib.office_program model = Model('Single_Zone_Simple', [room]) afn.generate(model.rooms, delta_pressure=8) # Check that walls have AFNCrack in face room = model.rooms[0] faces = room.faces # Test that no cracks to floors were added assert faces[0].properties.energy.vent_crack is None # Test that we have cracks in walls assert isinstance(faces[1].properties.energy.vent_crack, AFNCrack) assert isinstance(faces[2].properties.energy.vent_crack, AFNCrack) assert isinstance(faces[3].properties.energy.vent_crack, AFNCrack) assert isinstance(faces[4].properties.energy.vent_crack, AFNCrack) assert isinstance(faces[5].properties.energy.vent_crack, AFNCrack) # Calculate parameters for checks qv = room.properties.energy.infiltration.flow_per_exterior_area n = 0.65 dP = 8 d = afn._air_density_from_pressure() # Test flow coefficients and exponents for i in range(1, 6): # check opaque areas chk_cq = (qv * d) / (dP**n) * faces[i].area cq = faces[i].properties.energy.vent_crack.flow_coefficient n = faces[i].properties.energy.vent_crack.flow_exponent assert chk_cq == pytest.approx(cq, abs=1e-10) assert 0.65 == pytest.approx(n, abs=1e-10) # confirm that auto-calculated flow coefficients produce room.infiltration rate total_room_flow = 0 for i in range(1, 6): crack = faces[i].properties.energy.vent_crack cq = crack.flow_coefficient total_room_flow += cq * (dP**crack.flow_exponent) / d chk_infil = total_room_flow / room.exposed_area # m3/s/m2 assert qv == pytest.approx(chk_infil, abs=1e-10)
def test_afn_multizone_air_boundary(): """Test adding afn to multiple zones with an AirBoundary between them.""" # South Room szone_pts = Face3D( [Point3D(0, 0), Point3D(20, 0), Point3D(20, 10), Point3D(0, 10)]) sroom = Room.from_polyface3d('SouthRoom', Polyface3D.from_offset_face(szone_pts, 3)) # North Room nzone_pts = Face3D( [Point3D(0, 10), Point3D(20, 10), Point3D(20, 20), Point3D(0, 20)]) nroom = Room.from_polyface3d('NorthRoom', Polyface3D.from_offset_face(nzone_pts, 3)) # Make interior faces rooms = [sroom, nroom] adj_info = Room.solve_adjacency(rooms, 0.01) inter_sface3 = adj_info['adjacent_faces'][0][0] inter_nface1 = adj_info['adjacent_faces'][0][1] inter_sface3.type = face_types.air_boundary inter_nface1.type = face_types.air_boundary # Make afn afn.generate(rooms) sface3_crack = inter_sface3.properties.energy.vent_crack nface1_crack = inter_nface1.properties.energy.vent_crack assert sface3_crack is not None assert nface1_crack is not None assert sface3_crack.flow_coefficient > 50 # ensure it's nice and large assert nface1_crack.flow_coefficient > 50 # ensure it's nice and large assert sface3_crack.flow_exponent == 0.5 assert nface1_crack.flow_exponent == 0.5
def test_remove_colinear_vertices_envelope(): """Test the remove_colinear_vertices_envelope method.""" pts_1 = (Point3D(0, 0), Point3D(1, 0), Point3D(2, 0), Point3D(2, 2), Point3D(0, 2)) pf_1 = Polyface3D.from_offset_face(Face3D(pts_1), 3) room_1 = Room.from_polyface3d('Zone1', pf_1) pts_2 = (Point3D(0.5, 2, 0.5), Point3D(1, 2, 0.5), Point3D(1.5, 2, 0.5), Point3D(1.5, 2, 2), Point3D(0.5, 2, 2)) ap_2 = Aperture('TestAperture1', Face3D(pts_2)) room_1[-3].add_aperture(ap_2) assert len(room_1[0].geometry.vertices) == 5 assert len(ap_2.geometry.vertices) == 5 room_1.remove_colinear_vertices_envelope(0.0001) assert len(room_1[0].geometry.vertices) == 4 assert len(ap_2.geometry.vertices) == 4
def test_compute_bounding_box_extents_simple(): """Test the bounding box extents calculation of ladybug_geometry.""" # South Room 1: 20 x 6 x 3 szone1 = Face3D( [Point3D(-10, -3), Point3D(10, -3), Point3D(10, 3), Point3D(-10, 3)]) sroom1 = Room.from_polyface3d('SouthRoom1', Polyface3D.from_offset_face(szone1, 3)) theta = 90.0 sroom1.rotate_xy(theta, Point3D(0, 0, 0)) xx, yy, zz = bounding_box_extents([sroom1.geometry], math.radians(theta)) assert xx == pytest.approx(20, abs=1e-10) assert yy == pytest.approx(6, abs=1e-10) assert zz == pytest.approx(3, abs=1e-10)
def test_intersect_plane(): """Test the Polyface3D intersect_plane method.""" pts = (Point3D(0, 0, 2), Point3D(2, 0, 2), Point3D(2, 1, 2), Point3D(1, 1, 2), Point3D(1, 2, 2), Point3D(0, 2, 2)) plane = Plane(Vector3D(0, 0, 1), Point3D(0, 0, 2)) face = Face3D(pts, plane) polyface = Polyface3D.from_offset_face(face, 1) plane_1 = Plane(Vector3D(0, 1, 0), Point3D(0.5, 0.5, 0)) plane_2 = Plane(Vector3D(1, 0, 0), Point3D(0.5, 0.5, 0)) plane_3 = Plane(Vector3D(0, 1, 0), Point3D(0.5, 1.5, 0)) plane_4 = Plane(Vector3D(0, 1, 0), Point3D(0, 3, 0)) plane_5 = Plane(Vector3D(1, 1, 0), Point3D(0, 2.5, 0)) assert len(polyface.intersect_plane(plane_1)) == 4 assert len(polyface.intersect_plane(plane_2)) == 4 assert len(polyface.intersect_plane(plane_3)) == 4 assert len(polyface.intersect_plane(plane_4)) == 0 assert len(polyface.intersect_plane(plane_5)) == 8
def _rooms_from_footprint( footprint, room_ids, unique_id, floor_to_floor_height, orientation_angle, story_count, outdoor_roof, ground_floor): """Function to convert footprint geometry into full honeybee rooms.""" # extrude the footprint into solids first_floor = [Polyface3D.from_offset_face(geo, floor_to_floor_height) for geo in footprint] # rotate the geometries if an orientation angle is specified if orientation_angle != 0: angle, origin = math.radians(orientation_angle), Point3D() first_floor = [geo.rotate_xy(angle, origin) for geo in first_floor] # create the initial rooms for the first floor rooms = [] for polyface, rmid in zip(first_floor, room_ids): rooms.append(Room.from_polyface3d('{}_{}'.format(rmid, unique_id), polyface)) # if there are multiple stories, duplicate the first floor rooms if story_count != 1: all_rooms = [] for i in range(story_count): for room in rooms: new_room = room.duplicate() new_room.add_prefix('Floor{}'.format(i + 1)) m_vec = Vector3D(0, 0, floor_to_floor_height * i) new_room.move(m_vec) all_rooms.append(new_room) rooms = all_rooms # assign readable names for the display_name (without the UUID) for room in rooms: room.display_name = room.identifier[:-9] # assign adiabatic boundary conditions if requested if not outdoor_roof and ad_bc: for room in rooms[-len(first_floor):]: room[-1].boundary_condition = ad_bc # make the roof adiabatic if not ground_floor and ad_bc: for room in rooms[:len(first_floor)]: room[0].boundary_condition = ad_bc # make the floor adiabatic return rooms
def test_polyface3d_init_from_offset_face_hexagon(): """Test the initalization of Poyface3D from_offset_face.""" face = Face3D.from_regular_polygon(6, 2) polyface = Polyface3D.from_offset_face(face, 2) assert len(polyface.vertices) == 12 assert len(polyface.face_indices) == 8 assert len(polyface.faces) == 8 assert len(polyface.edge_indices) == 18 assert len(polyface.edges) == 18 assert len(polyface.naked_edges) == 0 assert len(polyface.non_manifold_edges) == 0 assert len(polyface.internal_edges) == 18 assert polyface.area == pytest.approx(44.784609, rel=1e-3) assert polyface.volume == pytest.approx(20.78460, rel=1e-3) assert polyface.is_solid assert polyface.faces[0].normal.z == pytest.approx(-1, rel=1e-3) assert polyface.faces[-1].normal.z == pytest.approx(1, rel=1e-3) for face in polyface.faces: assert not face.is_clockwise
def test_compute_building_type(): """Test calculation of building type.""" # Test lowrise: 21 x 21 x 3 # South Room: 21 x 10.5 szone_pts = Face3D( [Point3D(0, 0), Point3D(21, 0), Point3D(21, 10.5), Point3D(0, 5)]) sroom = Room.from_polyface3d('SouthRoom', Polyface3D.from_offset_face(szone_pts, 3)) # North Room: 21 x 10.5 nzone_pts = Face3D( [Point3D(0, 10.5), Point3D(21, 10.5), Point3D(21, 21), Point3D(0, 21)]) nroom = Room.from_polyface3d('NorthRoom', Polyface3D.from_offset_face(nzone_pts, 3)) # Add detail and create the model sroom[3].apertures_by_ratio(0.3) # Window on south face nroom[1].apertures_by_ratio(0.3) # Window on north face rooms = [sroom, nroom] model = Model('Test_Zone', rooms) # autocalculate the building type model.properties.energy.autocalculate_ventilation_simulation_control() btype = model.properties.energy.ventilation_simulation_control.building_type assert btype == 'LowRise' # Test highrise 21 x 21 x 63 # South Room: 21 x 10.5 szone_pts = Face3D( [Point3D(0, 0), Point3D(21, 0), Point3D(21, 10.5), Point3D(0, 10.5)]) sroom = Room.from_polyface3d('SouthRoom', Polyface3D.from_offset_face(szone_pts, 63)) # North Room: 21 x 10.5 nzone_pts = Face3D( [Point3D(0, 10.5), Point3D(21, 10.5), Point3D(21, 21), Point3D(0, 21)]) nroom = Room.from_polyface3d('NorthRoom', Polyface3D.from_offset_face(nzone_pts, 63)) # Add detail and create the model rooms = [sroom, nroom] model = Model('Test_Zone', rooms) model.rotate_xy(3, rooms[0].geometry.vertices[0]) # autocalculate the building type model.properties.energy.autocalculate_ventilation_simulation_control() btype = model.properties.energy.ventilation_simulation_control.building_type assert btype == 'LowRise' # Test highrise 21 x 21 x 63.1 # South Room: 21 x 10.5 szone_pts = Face3D( [Point3D(0, 0), Point3D(21, 0), Point3D(21, 10.5), Point3D(0, 10.5)]) sroom = Room.from_polyface3d('SouthRoom', Polyface3D.from_offset_face(szone_pts, 63.1)) # North Room: 21 x 10.5 nzone_pts = Face3D( [Point3D(0, 10.5), Point3D(21, 10.5), Point3D(21, 21), Point3D(0, 21)]) nroom = Room.from_polyface3d('NorthRoom', Polyface3D.from_offset_face(nzone_pts, 63.1)) # Add detail and create the model rooms = [sroom, nroom] model = Model('Test_Zone', rooms) # autocalculate the building type model.properties.energy.autocalculate_ventilation_simulation_control() btype = model.properties.energy.ventilation_simulation_control.building_type assert btype == 'HighRise'
def test_afn_multizone(): """Test adding afn to multiple zones with windows.""" # South Room szone_pts = Face3D( [Point3D(0, 0), Point3D(20, 0), Point3D(20, 10), Point3D(0, 10)]) sroom = Room.from_polyface3d('SouthRoom', Polyface3D.from_offset_face(szone_pts, 3)) # North Room nzone_pts = Face3D( [Point3D(0, 10), Point3D(20, 10), Point3D(20, 20), Point3D(0, 20)]) nroom = Room.from_polyface3d('NorthRoom', Polyface3D.from_offset_face(nzone_pts, 3)) # Add adjacent interior windows sroom[3].apertures_by_ratio(0.3) # Window on south face nroom[1].apertures_by_ratio(0.3) # Window on north face # rooms rooms = [sroom, nroom] for room in rooms: # Add program and hvac room.properties.energy.program_type = prog_type_lib.office_program # Make model model = Model('Two_Zone_Simple', rooms) # Make interior faces adj_info = Room.solve_adjacency(rooms, 0.01) inter_sface3 = adj_info['adjacent_faces'][0][0] inter_nface1 = adj_info['adjacent_faces'][0][1] inter_saper3 = adj_info['adjacent_apertures'][0][0] inter_naper1 = adj_info['adjacent_apertures'][0][1] # confirm face adjacencies assert len(adj_info['adjacent_faces']) == 1 assert isinstance(inter_sface3.boundary_condition, Surface) assert isinstance(inter_nface1.boundary_condition, Surface) # confirm aper adjacencies assert len(adj_info['adjacent_apertures']) == 1 assert isinstance(inter_saper3.boundary_condition, Surface) assert isinstance(inter_naper1.boundary_condition, Surface) # Make afn afn.generate(model.rooms) # get cracks int_cracks = CRACK_TEMPLATE_DATA['internal_medium_cracks'] # Check internal cracks in adjacent faces int_crack = sroom[3].properties.energy.vent_crack ref_area = sroom[3].area - sroom[3].apertures[0].area assert int_crack.flow_coefficient == pytest.approx( int_cracks['wall_flow_cof'] * ref_area, abs=1e-10) assert int_crack.flow_exponent == pytest.approx( int_cracks['wall_flow_exp'], abs=1e-10) int_crack = nroom[1].properties.energy.vent_crack assert int_crack.flow_coefficient == pytest.approx( int_cracks['wall_flow_cof'] * ref_area, abs=1e-10) assert int_crack.flow_exponent == pytest.approx( int_cracks['wall_flow_exp'], abs=1e-10) # Check that there is only one vent opening for interior walls assert isinstance(sroom[3].apertures[0].properties.energy.vent_opening, VentilationOpening) assert isinstance(nroom[1].apertures[0].properties.energy.vent_opening, VentilationOpening) # confirm that auto-calculated flow coefficients produce room.infiltration rate d = afn._air_density_from_pressure() dP = 4 for room in model.rooms: total_room_flow = 0 faces = room.faces qv = room.properties.energy.infiltration.flow_per_exterior_area for face in faces: if isinstance(face.boundary_condition, Outdoors): crack = face.properties.energy.vent_crack cq = crack.flow_coefficient total_room_flow += cq * (dP**crack.flow_exponent) / d chk_infil = total_room_flow / room.exposed_area # m3/s/m2 assert qv == pytest.approx(chk_infil, abs=1e-10)
def model_energy_afn_multizone(directory): # south Room szone_pts = Face3D( [Point3D(0, 0), Point3D(20, 0), Point3D(20, 10), Point3D(0, 10)]) sroom = Room.from_polyface3d('SouthRoom', Polyface3D.from_offset_face(szone_pts, 3)) # north Room nzone_pts = Face3D( [Point3D(0, 10), Point3D(20, 10), Point3D(20, 20), Point3D(0, 20)]) nroom = Room.from_polyface3d('NorthRoom', Polyface3D.from_offset_face(nzone_pts, 3)) # add exterior windows on east/west faces sroom[2].apertures_by_ratio(0.3) nroom[4].apertures_by_ratio(0.3) sroom[2].apertures[0].is_operable = True nroom[4].apertures[0].is_operable = True # add small interior windows on north/south faces sroom[3].apertures_by_ratio(0.15) nroom[1].apertures_by_ratio(0.15) sroom[3].apertures[0].is_operable = True nroom[1].apertures[0].is_operable = True # ventilation openings vent_openings = VentilationOpening(fraction_area_operable=1, fraction_height_operable=1, discharge_coefficient=0.6, wind_cross_vent=False, flow_coefficient_closed=0.001, flow_exponent_closed=0.667, two_way_threshold=0.0001) sroom.properties.energy.assign_ventilation_opening(vent_openings) nroom.properties.energy.assign_ventilation_opening( vent_openings.duplicate()) # make ventilation control heat_setpt = ScheduleRuleset.from_constant_value( 'House Heating', 20, schedule_types.temperature) cool_setpt = ScheduleRuleset.from_constant_value( 'House Cooling', 28, schedule_types.temperature) setpoint = Setpoint('House Setpoint', heat_setpt, cool_setpt) sroom.properties.energy.setpoint = setpoint nroom.properties.energy.setpoint = setpoint.duplicate() vent_control = VentilationControl(22, 27, 12, 30) sroom.properties.energy.window_vent_control = vent_control nroom.properties.energy.window_vent_control = vent_control.duplicate() # rooms rooms = [sroom, nroom] for room in rooms: # Add program and hvac room.properties.energy.program_type = prog_type_lib.office_program # make model model = Model('Two_Zone_Simple', rooms) vsc = VentilationSimulationControl( vent_control_type='MultiZoneWithoutDistribution', building_type='LowRise', long_axis_angle=0, aspect_ratio=1) model.properties.energy.ventilation_simulation_control = vsc # make interior faces Room.solve_adjacency(rooms, 0.01) # make afn afn.generate(model.rooms) dest_file = os.path.join(directory, 'model_energy_afn.json') with open(dest_file, 'w') as fp: json.dump(model.to_dict(included_prop=['energy']), fp, indent=4)
def test_afn_single_zone(): """Test adding afn to single zone with window and door.""" zone_pts = Face3D( [Point3D(0, 0), Point3D(20, 0), Point3D(20, 10), Point3D(0, 10)]) room = Room.from_polyface3d('SouthRoom', Polyface3D.from_offset_face(zone_pts, 3)) # Add door and window door_pts = [ Point3D(2, 10, 0.01), Point3D(4, 10, 0.01), Point3D(4, 10, 2.50), Point3D(2, 10, 2.50) ] door = Door('FrontDoor', Face3D(door_pts)) room[3].add_door(door) # Door to north face room[1].apertures_by_ratio(0.3) # Window on south face room.properties.energy.program_type = prog_type_lib.office_program # Make model model = Model('Single_Zone_Simple', [room]) afn.generate(model.rooms) # Check that walls have AFNCrack in face room = model.rooms[0] faces = room.faces # Test that no cracks to roofs/floors were added assert faces[0].properties.energy.vent_crack is None # Test that we have cracks in walls assert isinstance(faces[1].properties.energy.vent_crack, AFNCrack) assert isinstance(faces[2].properties.energy.vent_crack, AFNCrack) assert isinstance(faces[3].properties.energy.vent_crack, AFNCrack) assert isinstance(faces[4].properties.energy.vent_crack, AFNCrack) assert isinstance(faces[5].properties.energy.vent_crack, AFNCrack) # Test that we have ventilation openings assert isinstance(faces[1].apertures[0].properties.energy.vent_opening, VentilationOpening) assert isinstance(faces[3].doors[0].properties.energy.vent_opening, VentilationOpening) # Calculate parameters for checks qv = room.properties.energy.infiltration.flow_per_exterior_area n = 0.65 dP = 4 d = afn._air_density_from_pressure() # Test flow coefficients and exponents for i in range(1, 6): opening_area = 0 # check openings if i == 1 or i == 3: if i == 1: opening_area = faces[i].apertures[0].area vface = faces[i].apertures[0] elif i == 3: opening_area = faces[i].doors[0].area vface = faces[i].doors[0] v = vface.properties.energy.vent_opening chk_cq = qv * d / (dP**n) * vface.area / vface.perimeter cq = v.flow_coefficient_closed n = v.flow_exponent_closed assert chk_cq == pytest.approx(cq, abs=1e-10) assert 0.65 == pytest.approx(n, abs=1e-10) # check opaque areas chk_cq = qv * d / (dP**n) * (faces[i].area - opening_area) cq = faces[i].properties.energy.vent_crack.flow_coefficient n = faces[i].properties.energy.vent_crack.flow_exponent assert chk_cq == pytest.approx(cq, abs=1e-10) assert 0.65 == pytest.approx(n, abs=1e-10) # confirm that auto-calculated flow coefficients produce room.infiltration rate total_room_flow = 0 for i in range(1, 6): if i == 1 or i == 3: if i == 1: vface = faces[i].apertures[0] elif i == 3: vface = faces[i].doors[0] v = vface.properties.energy.vent_opening cq = v.flow_coefficient_closed * vface.perimeter total_room_flow += cq * (dP**v.flow_exponent_closed) / d crack = faces[i].properties.energy.vent_crack cq = crack.flow_coefficient total_room_flow += cq * (dP**crack.flow_exponent) / d chk_infil = total_room_flow / room.exposed_area # m3/s/m2 assert qv == pytest.approx(chk_infil, abs=1e-10)
def rectangle_plan(width, length, floor_to_floor_height, perimeter_offset, story_count, orientation_angle, outdoor_roof, ground_floor, units, tolerance, output_file): """Create a model with a rectangular floor plan.\n Note that the resulting Rooms in the model won't have any windows or solved adjacencies and the edit commands should be used for this purpose.\n \n Args:\n width: Number for the width of the plan (in the X direction).\n depth: Number for the depth of the plan (in the Y direction).\n floor_to_floor_height: Number for the height of each floor of the model (in the Z direction). """ try: unique_id = str(uuid.uuid4())[:8] # unique identifier for the rooms # create the geometry of the rooms for the first floor footprint = Face3D.from_rectangle(width, length) if perimeter_offset != 0: # use the straight skeleton methods assert perimeter_offset > 0, 'perimeter_offset cannot be less than than 0.' try: footprint = [] base = Polygon2D.from_rectangle(Point2D(), Vector2D(0, 1), width, length) sub_polys_perim, sub_polys_core = perimeter_core_subpolygons( polygon=base, distance=perimeter_offset, tol=tolerance) for s_poly in sub_polys_perim + sub_polys_core: sub_face = Face3D( [Point3D(pt.x, pt.y, 0) for pt in s_poly]) footprint.append(sub_face) except RuntimeError as e: footprint = [Face3D.from_rectangle(width, length)] else: footprint = [Face3D.from_rectangle(width, length)] first_floor = [ Polyface3D.from_offset_face(geo, floor_to_floor_height) for geo in footprint ] # rotate the geometries if an orientation angle is specified if orientation_angle != 0: angle, origin = math.radians(orientation_angle), Point3D() first_floor = [geo.rotate_xy(angle, origin) for geo in first_floor] # create the initial rooms for the first floor rmids = ['Room'] if len(first_floor) == 1 else [ 'Front', 'Right', 'Back', 'Left' ] if len(first_floor) == 5: rmids.append('Core') rooms = [] for polyface, rmid in zip(first_floor, rmids): rooms.append( Room.from_polyface3d('{}_{}'.format(rmid, unique_id), polyface)) # if there are multiple stories, duplicate the first floor rooms if story_count != 1: all_rooms = [] for i in range(story_count): for room in rooms: new_room = room.duplicate() new_room.add_prefix('Floor{}'.format(i + 1)) m_vec = Vector3D(0, 0, floor_to_floor_height * i) new_room.move(m_vec) all_rooms.append(new_room) rooms = all_rooms # assign adiabatic boundary conditions if requested if not outdoor_roof and ad_bc: for room in rooms[-len(first_floor):]: room[-1].boundary_condition = ad_bc # make the roof adiabatic if not ground_floor and ad_bc: for room in rooms[:len(first_floor)]: room[0].boundary_condition = ad_bc # make the floor adiabatic # create the model object model_id = 'Rectangle_Plan_Model_{}'.format(unique_id) model = Model(model_id, rooms, units=units, tolerance=tolerance, angle_tolerance=1) # write the model out to the file or stdout output_file.write(json.dumps(model.to_dict())) except Exception as e: _logger.exception( 'Rectangle plan model creation failed.\n{}'.format(e)) sys.exit(1) else: sys.exit(0)
def test_compute_aspect_ratio(): """Test calculation of aspect ratio.""" # South Room: 21 x 21 x 3 szone_pts = Face3D( [Point3D(0, 0), Point3D(21, 0), Point3D(21, 21), Point3D(0, 10)]) sroom = Room.from_polyface3d('SouthRoom', Polyface3D.from_offset_face(szone_pts, 3)) # add detail and create the Model rooms = [sroom] model = Model('Test_Zone', rooms) # autocalculate the aspect ratio model.properties.energy.autocalculate_ventilation_simulation_control() ar = model.properties.energy.ventilation_simulation_control.aspect_ratio assert ar == pytest.approx(1.0, abs=1e-10) axis = model.properties.energy.ventilation_simulation_control.long_axis_angle assert axis == 0 # Test lowrise 15 x 21 x 3 szone_pts = Face3D( [Point3D(0, 0), Point3D(21, 0), Point3D(21, 10), Point3D(0, 10)]) sroom = Room.from_polyface3d('SouthRoom', Polyface3D.from_offset_face(szone_pts, 3)) # North Room: 21 x 15 x 3 nzone_pts = Face3D( [Point3D(0, 10), Point3D(21, 10), Point3D(21, 15), Point3D(0, 15)]) nroom = Room.from_polyface3d('NorthRoom', Polyface3D.from_offset_face(nzone_pts, 3)) # add detail and create the model rooms = [sroom, nroom] model = Model('Test_Zone', rooms) # autocalculate the aspect ratio model.properties.energy.autocalculate_ventilation_simulation_control() ar = model.properties.energy.ventilation_simulation_control.aspect_ratio assert ar == pytest.approx(15.0 / 21.0, abs=1e-10) axis = model.properties.energy.ventilation_simulation_control.long_axis_angle assert axis == 90 # Test 21 x 22 x 3 szone_pts = Face3D( [Point3D(0, 0), Point3D(21, 0), Point3D(21, 10.5), Point3D(0, 10.5)]) sroom = Room.from_polyface3d('SouthRoom', Polyface3D.from_offset_face(szone_pts, 63.1)) nzone_pts = Face3D( [Point3D(0, 10.5), Point3D(21, 10.5), Point3D(21, 22), Point3D(0, 22)]) nroom = Room.from_polyface3d('NorthRoom', Polyface3D.from_offset_face(nzone_pts, 3)) # add detail and create the model rooms = [sroom, nroom] model = Model('Test_Zone', rooms) # autocalculate the aspect ratio model.properties.energy.autocalculate_ventilation_simulation_control() ar = model.properties.energy.ventilation_simulation_control.aspect_ratio assert ar == pytest.approx(21.0 / 22.0, abs=1e-10) axis = model.properties.energy.ventilation_simulation_control.long_axis_angle assert axis == 0