MEP01

Proof of Concept for Use of topologicpy for MEP

Caution

Disclaimer: I am NOT an MEP expert! The assumptions and calculations in this notebook are probably completely wrong. Yet, the general concept should still apply. Always form your own impressions and make your own decisions. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

Import the needed python libraries


from topologicpy.Vertex import Vertex
from topologicpy.Edge import Edge
from topologicpy.Wire import Wire
from topologicpy.Face import Face
from topologicpy.Shell import Shell
from topologicpy.Cell import Cell
from topologicpy.CellComplex import CellComplex
from topologicpy.Cluster import Cluster
from topologicpy.Topology import Topology
from topologicpy.Graph import Graph
from topologicpy.Dictionary import Dictionary
from topologicpy.Vector import Vector
from topologicpy.Helper import Helper
from topologicpy.Plotly import Plotly

Import or Create the building geometry (CellComplex with Apertures)

building = CellComplex.Prism(width=10, length=12, height=3, uSides=1, vSides=3, wSides=1, placement="lowerleft")
corridor = Cell.Prism(origin=Vertex.ByCoordinates(4,0,0), width=2,length=12,height=3, placement="lowerleft")
building = Topology.Merge(building, corridor)
source = Cell.Prism(origin=Vertex.ByCoordinates(4,-2,0), width=2, length=2, height=3, placement="lowerleft")
building = Topology.Merge(building, source)
selectors = []
cells = Topology.Cells(building)
for cell in cells:
    centroid = Topology.Centroid(cell)
    if Vertex.X(centroid) < 4 or Vertex.X(centroid) > 6:
        d = Dictionary.ByKeyValue("name", "room")
        centroid = Topology.SetDictionary(centroid, d)
    elif Vertex.Y(centroid) < 0:
        d = Dictionary.ByKeyValue("name", "source")
        centroid = Topology.SetDictionary(centroid, d)
    else:
        d = Dictionary.ByKeyValue("name", "corridor")
        centroid = Topology.SetDictionary(centroid, d)
    selectors.append(centroid)

building = Topology.TransferDictionariesBySelectors(building, selectors, tranCells=True)

d = CellComplex.Decompose(building)
int_walls = d['internalVerticalFaces']
selected_walls = []
for int_wall in int_walls:
    cells = Topology.SuperTopologies(int_wall, building, topologyType="cell")
    types = []
    for cell in cells:
        d = Topology.Dictionary(cell)
        room_type = Dictionary.ValueAtKey(d, "name")
        types.append(room_type)
    if "room" in types and "corridor" in types:
        selected_walls.append(int_wall)
    elif "corridor" in types and "source" in types:
        selected_walls.append(int_wall)
    elif types == ["corridor", "corridor"]:
        selected_walls.append(int_wall)
apertures = []
for w in selected_walls:
    centroid = Topology.Centroid(w)
    apertures.append(Topology.Scale(w, origin=centroid, x=0.5, y=0.5, z=0.5))

building = Topology.AddApertures(building, apertures, subTopologyType="face")

Derive a Tree Graph from the building

graph = Graph.ByTopology(building, direct=False, directApertures=True)
graph = Graph.Tree(graph, Vertex.ByCoordinates(5,-1,1.5))

Visualize the Building and the Tree Graph

edges = Graph.Edges(graph)
cones = []
for edge in edges:
    base = Edge.VertexByParameter(edge, 0.85)
    top = Edge.EndVertex(edge)
    height = Vertex.Distance(base, top)
    direction = Edge.Direction(edge)
    cones.append(Cell.Cone(origin=base, baseRadius=0.1, height=height, direction=direction, placement="bottom"))
cones = Cluster.ByTopologies(cones)
g_top = Graph.Topology(graph)
data01 = Plotly.DataByTopology(g_top, vertexSize=4, edgeColor="red", edgeWidth=3, vertexColor="blue")
data02 = Plotly.DataByTopology(building)
data03 = Plotly.DataByTopology(cones, showVertices=False, faceOpacity=1, faceColor="black")
figure = Plotly.FigureByData(data01+data02+data03)
Plotly.Show(figure)

Assign attributes to graph edges (ducts)

edges = Graph.Edges(graph)
for edge in edges:
    sv = Edge.StartVertex(edge)
    ev = Edge.EndVertex(edge)
    length = Edge.Length(edge)
    if Vertex.IsInternal(sv, source):
        diam = 0.5
    elif Vertex.IsInternal(sv, corridor) and Vertex.IsInternal(ev, corridor):
        diam = 0.4
    else:
        diam = 0.2
    d = Dictionary.ByKeysValues(["diameter", "airflow", "label"], [diam, 1, "Diam: "+str(diam)+"/ Length: "+str(length)])
    edge = Topology.SetDictionary(edge, d)    

Visualize ducts in 3D

edges = Graph.Edges(graph)
ducts = []
for edge in edges:
    origin = Edge.StartVertex(edge)
    direction = Edge.Direction(edge)
    d = Topology.Dictionary(edge)
    diameter = Dictionary.ValueAtKey(d, "diameter")
    direction = Edge.Direction(edge)
    height = Edge.Length(edge)
    duct = Cell.Cylinder(origin=origin, radius=diameter*0.5, height=height, direction=direction, placement="bottom")
    ducts.append(duct)
data01 = Plotly.DataByTopology(Cluster.ByTopologies(ducts), showVertices=False, faceColor="red", faceOpacity=1)
data02 = Plotly.DataByTopology(building)
figure = Plotly.FigureByData(data01+data02)
Plotly.Show(figure)

Define a Pressure Drop function. This is most likely completely wrong!

def compute_pressure_drop_hvac(graph, air_density):
    """
    Compute pressure drop in an HVAC system using the given formula.

    Parameters:
    - graph: Directed graph representing the HVAC system (networkx.DiGraph).
    - airflow_rate: Airflow rate through each duct (dict of edges to airflow rates).
    - duct_diameter: Diameter of each duct (dict of edges to diameters).
    - duct_length: Length of each duct (dict of edges to lengths).
    - air_density: Density of the air.

    Returns:
    - pressure_drop: Dictionary of nodes to pressure drops.
    """
    vertices = Graph.Vertices(graph)
    for v in vertices:
        d = Dictionary.ByKeysValues(["pressure_drop", "label"], [0, "P.D. 0"])
        v = Topology.SetDictionary(v, d)

    edges = Graph.Edges(graph)
    for edge in edges:
        d = Topology.Dictionary(edge)
        airflow = Dictionary.ValueAtKey(d, "airflow")
        diameter = Dictionary.ValueAtKey(d, "diameter")
        length = Edge.Length(edge)

        velocity = airflow / (3.14159 * (diameter / 2)**2)  # Calculate velocity based on airflow and duct diameter
        friction_factor = 0.03  # You may need to adjust this based on the specific characteristics of your system
        ev = Edge.EndVertex(edge)
        ev = Graph.NearestVertex(graph, ev)
        d_v = Topology.Dictionary(ev)
        pressure_drop = Dictionary.ValueAtKey(d_v, "pressure_drop")
        pressure_drop += friction_factor * (length / diameter) * (air_density * velocity**2 / 2)
        d_v = Dictionary.ByKeysValues(["pressure_drop", "label"], [pressure_drop, "P.D. "+str(pressure_drop)])
        ev = Topology.SetDictionary(ev, d_v)

    return graph

Calculate Pressure Drop

air_density = 1.2  # kg/m^3

graph = compute_pressure_drop_hvac(graph, air_density)
vertices = Graph.Vertices(graph)
groups = []
for v in vertices:
    d = Topology.Dictionary(v)
    print(Dictionary.Keys(d), Dictionary.Values(d))
    p_d = Dictionary.ValueAtKey(d, "pressure_drop")
    groups.append(p_d)
groups = list(set(groups))
['label', 'pressure_drop'] ['P.D. 273.5676579795474', 273.5676579795474]
['label', 'pressure_drop'] ['P.D. 11.398652415814475', 11.398652415814475]
['label', 'pressure_drop'] ['P.D. 273.5676579795474', 273.5676579795474]
['label', 'pressure_drop'] ['P.D. 273.5676579795474', 273.5676579795474]
['label', 'pressure_drop'] ['P.D. 11.398652415814475', 11.398652415814475]
['label', 'pressure_drop'] ['P.D. 273.5676579795474', 273.5676579795474]
['label', 'pressure_drop'] ['P.D. 2.8013328177105667', 2.8013328177105667]
['label', 'pressure_drop'] ['P.D. 273.5676579795474', 273.5676579795474]
['label', 'pressure_drop'] ['P.D. 0', 0]
['label', 'pressure_drop'] ['P.D. 273.5676579795474', 273.5676579795474]

Visualise Pressure Drop in Pyvis

status = Graph.PyvisGraph(graph, "mep01-vis.html", vertexGroupKey="pressure_drop", vertexGroups=groups, vertexLabelKey="label", edgeLabelKey="label")
mep01-vis.html
gio: file:///home/jovyan/topologicpy/tutorials/mep01-vis.html: Failed to find default application for content type ‘text/html’
from IPython.display import IFrame

IFrame("mep01-vis.html", width=1200, height = 1200)