feature: add pipe sizing to dhn analysis

This commit is contained in:
Majid Rezaei 2024-08-01 11:39:05 -04:00
parent 2ca52c157a
commit eb26c48627
9 changed files with 591 additions and 896 deletions

111
district_heating_network.py Normal file
View File

@ -0,0 +1,111 @@
from scripts.district_heating_network.directory_manager import DirectoryManager
import subprocess
from scripts.ep_run_enrich import energy_plus_workflow
from hub.imports.geometry_factory import GeometryFactory
from hub.helpers.dictionaries import Dictionaries
from hub.imports.construction_factory import ConstructionFactory
from hub.imports.usage_factory import UsageFactory
from hub.imports.weather_factory import WeatherFactory
from hub.imports.results_factory import ResultFactory
from scripts.energy_system_retrofit_report import EnergySystemRetrofitReport
from scripts.geojson_creator import process_geojson
from scripts import random_assignation
from hub.imports.energy_systems_factory import EnergySystemsFactory
from scripts.energy_system_sizing import SystemSizing
from scripts.solar_angles import CitySolarAngles
from scripts.pv_sizing_and_simulation import PVSizingSimulation
from scripts.energy_system_retrofit_results import consumption_data, cost_data
from scripts.energy_system_sizing_and_simulation_factory import EnergySystemsSimulationFactory
from scripts.costs.cost import Cost
from scripts.costs.constants import SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV, SYSTEM_RETROFIT_AND_PV, CURRENT_STATUS
import hub.helpers.constants as cte
from hub.exports.exports_factory import ExportsFactory
from scripts.pv_feasibility import pv_feasibility
import matplotlib.pyplot as plt
import numpy as np
from scripts.district_heating_network.district_heating_network_creator import DistrictHeatingNetworkCreator
from scripts.district_heating_network.district_heating_factory import DistrictHeatingFactory
import json
#%% --------------------------------------------------------------------------------------------------------------------
# Manage File Path
base_path = "./"
dir_manager = DirectoryManager(base_path)
# Input files directory
input_files_path = dir_manager.create_directory('input_files')
geojson_file_path = input_files_path / 'output_buildings.geojson'
pipe_data_file = input_files_path / 'pipe_data.json'
# Output files directory
output_path = dir_manager.create_directory('out_files')
# Subdirectories for output files
energy_plus_output_path = dir_manager.create_directory('out_files/energy_plus_outputs')
simulation_results_path = dir_manager.create_directory('out_files/simulation_results')
sra_output_path = dir_manager.create_directory('out_files/sra_outputs')
cost_analysis_output_path = dir_manager.create_directory('out_files/cost_analysis')
#%% --------------------------------------------------------------------------------------------------------------------
# Area Under Study
location = [45.4934614681437, -73.57982834742518]
#%% --------------------------------------------------------------------------------------------------------------------
# Create geojson of buildings
process_geojson(x=location[1], y=location[0], diff=0.001)
#%% --------------------------------------------------------------------------------------------------------------------
# Create ciry and run energyplus workflow
city = GeometryFactory(file_type='geojson',
path=geojson_file_path,
height_field='height',
year_of_construction_field='year_of_construction',
function_field='function',
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
ConstructionFactory('nrcan', city).enrich()
UsageFactory('nrcan', city).enrich()
WeatherFactory('epw', city).enrich()
# SRA
ExportsFactory('sra', city, output_path).export()
sra_path = (output_path / f'{city.name}_sra.xml').resolve()
subprocess.run(['sra', str(sra_path)])
ResultFactory('sra', city, output_path).enrich()
# EP Workflow
energy_plus_workflow(city, energy_plus_output_path)
#%% --------------------------------------------------------------------------------------------------------------------
# District Heating Network Creator
central_plant_locations = [(-73.57812571080625, 45.49499447346277)] # Add at least one location
roads_file = "./input_files/roads.json"
dhn_creator = DistrictHeatingNetworkCreator(geojson_file_path, roads_file, central_plant_locations)
network_graph = dhn_creator.run()
#%% --------------------------------------------------------------------------------------------------------------------
# Pipe and pump sizing
with open(pipe_data_file, 'r') as f:
pipe_data = json.load(f)
factory = DistrictHeatingFactory(
city=city,
graph=network_graph,
supply_temperature=80 + 273, # in Kelvin
return_temperature=60 + 273, # in Kelvin
simultaneity_factor=0.9
)
factory.enrich()
factory.sizing()
factory.calculate_diameters_and_costs(pipe_data)
pipe_groups, total_cost = factory.analyze_costs()
# Save the pipe groups with total costs to a CSV file
factory.save_pipe_groups_to_csv('pipe_groups.csv')
#%% --------------------------------------------------------------------------------------------------------------------

191
input_files/pipe_data.json Normal file
View File

@ -0,0 +1,191 @@
[
{
"DN": 16,
"inner_diameter": 16.1,
"outer_diameter": 21.3,
"thickness": 2.6,
"cost_per_meter": 320
},
{
"DN": 20,
"inner_diameter": 21.7,
"outer_diameter": 26.9,
"thickness": 2.6,
"cost_per_meter": 320
},
{
"DN": 25,
"inner_diameter": 27.3,
"outer_diameter": 33.7,
"thickness": 3.2,
"cost_per_meter": 320
},
{
"DN": 32,
"inner_diameter": 37.2,
"outer_diameter": 42.4,
"thickness": 2.6,
"cost_per_meter": 350
},
{
"DN": 40,
"inner_diameter": 43.1,
"outer_diameter": 48.3,
"thickness": 2.6,
"cost_per_meter": 375
},
{
"DN": 50,
"inner_diameter": 54.5,
"outer_diameter": 60.3,
"thickness": 2.9,
"cost_per_meter": 400
},
{
"DN": 65,
"inner_diameter": 70.3,
"outer_diameter": 76.1,
"thickness": 2.9,
"cost_per_meter": 450
},
{
"DN": 80,
"inner_diameter": 82.5,
"outer_diameter": 88.9,
"thickness": 3.2,
"cost_per_meter": 480
},
{
"DN": 90,
"inner_diameter": 100.8,
"outer_diameter": 108,
"thickness": 3.6,
"cost_per_meter": 480
},
{
"DN": 100,
"inner_diameter": 107.1,
"outer_diameter": 114.3,
"thickness": 3.6,
"cost_per_meter": 550
},
{
"DN": 110,
"inner_diameter": 125.8,
"outer_diameter": 133,
"thickness": 3.6,
"cost_per_meter": 550
},
{
"DN": 125,
"inner_diameter": 132.5,
"outer_diameter": 139.7,
"thickness": 3.6,
"cost_per_meter": 630
},
{
"DN": 140,
"inner_diameter": 151,
"outer_diameter": 159,
"thickness": 4,
"cost_per_meter": 700
},
{
"DN": 150,
"inner_diameter": 160.3,
"outer_diameter": 168.3,
"thickness": 4,
"cost_per_meter": 700
},
{
"DN": 180,
"inner_diameter": 184.7,
"outer_diameter": 193.7,
"thickness": 4.5,
"cost_per_meter": 700
},
{
"DN": 200,
"inner_diameter": 210.1,
"outer_diameter": 219.1,
"thickness": 4.5,
"cost_per_meter": 860
},
{
"DN": 250,
"inner_diameter": 263,
"outer_diameter": 273,
"thickness": 5,
"cost_per_meter": 860
},
{
"DN": 300,
"inner_diameter": 312.7,
"outer_diameter": 323.9,
"thickness": 5.6,
"cost_per_meter": 860
},
{
"DN": 350,
"inner_diameter": 344.4,
"outer_diameter": 355.6,
"thickness": 5.6,
"cost_per_meter": 860
},
{
"DN": 400,
"inner_diameter": 393.8,
"outer_diameter": 406.4,
"thickness": 6.3,
"cost_per_meter": 860
},
{
"DN": 450,
"inner_diameter": 444.4,
"outer_diameter": 457,
"thickness": 6.3,
"cost_per_meter": 860
},
{
"DN": 500,
"inner_diameter": 495.4,
"outer_diameter": 508,
"thickness": 6.3,
"cost_per_meter": 860
},
{
"DN": 600,
"inner_diameter": 595.8,
"outer_diameter": 610,
"thickness": 7.1,
"cost_per_meter": 860
},
{
"DN": 700,
"inner_diameter": 696.8,
"outer_diameter": 711,
"thickness": 7.1,
"cost_per_meter": 860
},
{
"DN": 800,
"inner_diameter": 797,
"outer_diameter": 813,
"thickness": 8,
"cost_per_meter": 860
},
{
"DN": 900,
"inner_diameter": 894,
"outer_diameter": 914,
"thickness": 10,
"cost_per_meter": 860
},
{
"DN": 1000,
"inner_diameter": 996,
"outer_diameter": 1016,
"thickness": 10,
"cost_per_meter": 860
}
]

View File

@ -25,6 +25,7 @@ from scripts.pv_feasibility import pv_feasibility
import matplotlib.pyplot as plt
from scripts.district_heating_network.district_heating_network_creator import DistrictHeatingNetworkCreator
from scripts.district_heating_network.road_processor import road_processor
from scripts.district_heating_network.district_heating_factory import DistrictHeatingFactory
base_path = Path(__file__).parent
dir_manager = DirectoryManager(base_path)

View File

@ -1,32 +1,248 @@
import networkx as nx
import CoolProp.CoolProp as CP
import math
import logging
import numpy as np
import csv
class DistrictHeatingFactory:
"""
DistrictHeatingFactory class
This class is responsible for managing the district heating network, including
enriching the network graph with building data, calculating flow rates,
sizing pipes, and analyzing costs.
"""
def __init__(self, city, graph):
def __init__(self, city, graph, supply_temperature, return_temperature, simultaneity_factor):
"""
Initialize the DistrictHeatingFactory object.
:param city: The city object containing buildings and their heating demands.
:param graph: The network graph representing the district heating network.
:param supply_temperature: The supply temperature of the heating fluid in the network (°C).
:param return_temperature: The return temperature of the heating fluid in the network (°C).
:param simultaneity_factor: The simultaneity factor used to adjust flow rates for non-building pipes.
"""
self._city = city
self._network_graph = graph
self._supply_temperature = supply_temperature
self._return_temperature = return_temperature
self.simultaneity_factor = simultaneity_factor
self.fluid = "Water" # The fluid used in the heating network
def enrich(self):
"""
Enrich the network graph nodes with attributes from the city buildings.
"""
Enrich the network graph nodes with the whole building object from the city buildings.
for node in self._network_graph.nodes(data=True):
node_id, node_attrs = node
This method associates each building node in the network graph with its corresponding
building object from the city, allowing access to heating demand data during calculations.
"""
for node_id, node_attrs in self._network_graph.nodes(data=True):
if node_attrs.get('type') == 'building':
building_name = node_attrs.get('name')
building_found = False
for building in self._city.buildings:
if building.name == building_name:
building_attrs = vars(building)
for attr, value in building_attrs.items():
if attr not in self._network_graph.nodes[node_id]:
self._network_graph.nodes[node_id][attr] = value
self._network_graph.nodes[node_id]['building_obj'] = building
building_found = True
break
if not building_found:
logging.error(msg=f"Building with name '{building_name}' not found in city.")
logging.error(msg=f"Building with name '{building_name}' not found in city.")
def calculate_flow_rates(self, A, Gext):
"""
Solve the linear system to find the flow rates in each branch.
:param A: The incidence matrix representing the network connections.
:param Gext: The external flow rates for each node in the network.
:return: The calculated flow rates for each edge, or None if an error occurs.
"""
try:
G = np.linalg.lstsq(A, Gext, rcond=None)[0]
return G
except np.linalg.LinAlgError as e:
logging.error(f"Error solving the linear system: {e}")
return None
def switch_nodes(self, A, edge_index, node_index, edge):
"""
Switch the in and out nodes for the given edge in the incidence matrix A.
:param A: The incidence matrix representing the network connections.
:param edge_index: The index of edges in the incidence matrix.
:param node_index: The index of nodes in the incidence matrix.
:param edge: The edge (u, v) to switch.
"""
u, v = edge
i = node_index[u]
j = node_index[v]
k = edge_index[edge]
A[i, k], A[j, k] = -A[i, k], -A[j, k]
def sizing(self):
"""
Calculate the hourly mass flow rates, assign them to the edges, and determine the pipe diameters.
This method generates the flow rates for each hour, adjusting the incidence matrix as needed to
ensure all flow rates are positive. It also applies the simultaneity factor to non-building pipes.
"""
num_nodes = self._network_graph.number_of_nodes()
num_edges = self._network_graph.number_of_edges()
A = np.zeros((num_nodes, num_edges)) # Initialize incidence matrix
node_index = {node: i for i, node in enumerate(self._network_graph.nodes())}
edge_index = {edge: i for i, edge in enumerate(self._network_graph.edges())}
# Initialize mass flow rate attribute for each edge
for u, v, data in self._network_graph.edges(data=True):
self._network_graph.edges[u, v]['mass_flow_rate'] = {"hour": [], "peak": None}
# Get the length of the hourly demand for the first building (assuming all buildings have the same length)
building = next(iter(self._city.buildings))
num_hours = len(building.heating_demand['hour'])
# Loop through each hour to generate Gext and solve AG = Gext
for hour in range(8760):
Gext = np.zeros(num_nodes)
# Calculate the hourly mass flow rates for each edge and fill Gext
for edge in self._network_graph.edges(data=True):
u, v, data = edge
for node in [u, v]:
if self._network_graph.nodes[node].get('type') == 'building':
building = self._network_graph.nodes[node].get('building_obj')
if building and "hour" in building.heating_demand:
hourly_demand = building.heating_demand["hour"][hour] # Get demand for current hour
specific_heat_capacity = CP.PropsSI('C', 'T', (self._supply_temperature + self._return_temperature) / 2,
'P', 101325, self.fluid)
mass_flow_rate = hourly_demand / 3600 / (
specific_heat_capacity * (self._supply_temperature - self._return_temperature))
Gext[node_index[node]] += mass_flow_rate
# Update incidence matrix A
i = node_index[u]
j = node_index[v]
k = edge_index[(u, v)]
A[i, k] = 1
A[j, k] = -1
# Solve for G (flow rates)
G = self.calculate_flow_rates(A, Gext)
if G is None:
return
# Check for negative flow rates and adjust A accordingly
iterations = 0
max_iterations = num_edges * 2
while any(flow_rate < 0 for flow_rate in G) and iterations < max_iterations:
for idx, flow_rate in enumerate(G):
if flow_rate < 0:
G[idx] = -G[idx] # Invert the sign directly
iterations += 1
# Store the final flow rates in the edges for this hour
for idx, (edge, flow_rate) in enumerate(zip(self._network_graph.edges(), G)):
u, v = edge
if not (self._network_graph.nodes[u].get('type') == 'building' or self._network_graph.nodes[v].get(
'type') == 'building'):
flow_rate *= self.simultaneity_factor # Apply simultaneity factor for non-building pipes
data = self._network_graph.edges[u, v]
data['mass_flow_rate']["hour"].append(flow_rate) # Append the calculated flow rate
# Calculate the peak flow rate for each edge
for u, v, data in self._network_graph.edges(data=True):
data['mass_flow_rate']['peak'] = max(data['mass_flow_rate']['hour'])
def calculate_diameters_and_costs(self, pipe_data):
"""
Calculate the diameter and costs of the pipes based on the maximum flow rate in each edge.
:param pipe_data: A list of dictionaries containing pipe specifications, including inner diameters
and costs per meter for different nominal diameters (DN).
"""
for u, v, data in self._network_graph.edges(data=True):
flow_rate = data.get('mass_flow_rate', {}).get('peak')
if flow_rate is not None:
try:
# Calculate the density of the fluid
density = CP.PropsSI('D', 'T', (self._supply_temperature + self._return_temperature) / 2, 'P', 101325,
self.fluid)
velocity = 0.9 # Desired fluid velocity in m/s
# Calculate the diameter of the pipe required for the given flow rate
diameter = math.sqrt((4 * abs(flow_rate)) / (density * velocity * math.pi)) * 1000 # Convert to mm
self._network_graph.edges[u, v]['diameter'] = diameter
# Match to the closest nominal diameter from the pipe data
closest_pipe = self.match_nominal_diameter(diameter, pipe_data)
self._network_graph.edges[u, v]['nominal_diameter'] = closest_pipe['DN']
self._network_graph.edges[u, v]['cost_per_meter'] = closest_pipe['cost_per_meter']
except Exception as e:
logging.error(f"Error calculating diameter or matching nominal diameter for edge ({u}, {v}): {e}")
def match_nominal_diameter(self, diameter, pipe_data):
"""
Match the calculated diameter to the closest nominal diameter.
:param diameter: The calculated diameter of the pipe (in mm).
:param pipe_data: A list of dictionaries containing pipe specifications, including inner diameters
and costs per meter for different nominal diameters (DN).
:return: The dictionary representing the pipe with the closest nominal diameter.
"""
closest_pipe = min(pipe_data, key=lambda x: abs(x['inner_diameter'] - diameter))
return closest_pipe
def analyze_costs(self):
"""
Analyze the costs based on the nominal diameters of the pipes.
This method calculates the total cost of piping for each nominal diameter group
and returns a summary of the grouped pipes and the total cost.
:return: A tuple containing the grouped pipe data and the total cost of piping.
"""
pipe_groups = {}
total_cost = 0 # Initialize total cost
for u, v, data in self._network_graph.edges(data=True):
dn = data.get('nominal_diameter')
if dn is not None:
pipe_length = self._network_graph.edges[u, v].get('length', 1) * 2 # Multiply by 2 for supply and return
cost_per_meter = data.get('cost_per_meter', 0)
if dn not in pipe_groups:
pipe_groups[dn] = {
'DN': dn,
'total_length': 0,
'cost_per_meter': cost_per_meter
}
pipe_groups[dn]['total_length'] += pipe_length
group_cost = pipe_length * cost_per_meter
total_cost += group_cost # Add to total cost
# Calculate total cost for each group
for group in pipe_groups.values():
group['total_cost'] = group['total_length'] * group['cost_per_meter']
return pipe_groups, total_cost # Return both the grouped data and total cost
def save_pipe_groups_to_csv(self, filename):
"""
Save the pipe groups and their total lengths to a CSV file.
:param filename: The name of the CSV file to save the data to.
"""
pipe_groups, _ = self.analyze_costs()
with open(filename, mode='w', newline='') as file:
writer = csv.writer(file)
# Write the header
writer.writerow(["Nominal Diameter (DN)", "Total Length (m)", "Cost per Meter", "Total Cost"])
# Write the data for each pipe group
for group in pipe_groups.values():
writer.writerow([
group['DN'],
group['total_length'],
group['cost_per_meter'],
group['total_cost']
])

View File

@ -8,9 +8,8 @@ from typing import List, Tuple
from rtree import index
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logging.getLogger('numexpr').setLevel(logging.ERROR)
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
logging.getLogger("numexpr").setLevel(logging.ERROR)
def haversine(lon1, lat1, lon2, lat2):
"""
@ -30,17 +29,21 @@ def haversine(lon1, lat1, lon2, lat2):
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
return R * c # Output distance in meters
class DistrictHeatingNetworkCreator:
def __init__(self, buildings_file: str, roads_file: str):
def __init__(self, buildings_file: str, roads_file: str, central_plant_locations: List[Tuple[float, float]]):
"""
Initialize the class with paths to the buildings and roads data files.
Initialize the class with paths to the buildings and roads data files, and central plant locations.
:param buildings_file: Path to the GeoJSON file containing building data.
:param roads_file: Path to the GeoJSON file containing roads data.
:param central_plant_locations: List of tuples containing the coordinates of central plant locations.
"""
if len(central_plant_locations) < 1:
raise ValueError("The list of central plant locations must have at least one member.")
self.buildings_file = buildings_file
self.roads_file = roads_file
self.central_plant_locations = central_plant_locations
def run(self) -> nx.Graph:
"""
@ -57,7 +60,8 @@ class DistrictHeatingNetworkCreator:
self._iteratively_remove_edges()
self._add_centroids_to_mst()
self._convert_edge_weights_to_meters()
return self.final_mst
self._create_final_network_graph()
return self.network_graph
except Exception as e:
logging.error(f"Error during network creation: {e}")
raise
@ -73,6 +77,7 @@ class DistrictHeatingNetworkCreator:
self.centroids = []
self.building_names = []
self.building_positions = []
buildings = city['features']
for building in buildings:
coordinates = building['geometry']['coordinates'][0]
@ -80,6 +85,14 @@ class DistrictHeatingNetworkCreator:
centroid = building_polygon.centroid
self.centroids.append(centroid)
self.building_names.append(str(building['id']))
self.building_positions.append((centroid.x, centroid.y))
# Add central plant locations as centroids
for i, loc in enumerate(self.central_plant_locations, start=1):
centroid = Point(loc)
self.centroids.append(centroid)
self.building_names.append(f'central_plant_{i}')
self.building_positions.append((centroid.x, centroid.y))
# Load road data
with open(self.roads_file, 'r') as file:
@ -184,7 +197,9 @@ class DistrictHeatingNetworkCreator:
for line in self.cleaned_lines:
coords = list(line.coords)
for i in range(len(coords) - 1):
self.G.add_edge(coords[i], coords[i + 1], weight=Point(coords[i]).distance(Point(coords[i + 1])))
u = coords[i]
v = coords[i + 1]
self.G.add_edge(u, v, weight=Point(coords[i]).distance(Point(coords[i + 1])))
except Exception as e:
logging.error(f"Error creating graph: {e}")
raise
@ -284,24 +299,22 @@ class DistrictHeatingNetworkCreator:
"""
try:
for i, centroid in enumerate(self.centroids):
centroid_tuple = (centroid.x, centroid.y)
building_name = self.building_names[i]
# Add the centroid node with its attributes
self.final_mst.add_node(centroid_tuple, type='building', name=building_name)
pos = (centroid.x, centroid.y)
node_type = 'building' if 'central_plant' not in building_name else 'generation'
self.final_mst.add_node(pos, type=node_type, name=building_name, pos=pos)
nearest_point = None
min_distance = float('inf')
for node in self.final_mst.nodes():
if self.final_mst.nodes[node].get('type') != 'building':
node_point = Point(node)
distance = centroid.distance(node_point)
if self.final_mst.nodes[node].get('type') != 'building' and self.final_mst.nodes[node].get('type') != 'generation':
distance = centroid.distance(Point(node))
if distance < min_distance:
min_distance = distance
nearest_point = node
if nearest_point:
self.final_mst.add_edge(centroid_tuple, nearest_point, weight=min_distance)
self.final_mst.add_edge(pos, nearest_point, weight=min_distance)
except Exception as e:
logging.error(f"Error adding centroids to MST: {e}")
raise
@ -312,22 +325,48 @@ class DistrictHeatingNetworkCreator:
"""
try:
for u, v, data in self.final_mst.edges(data=True):
lon1, lat1 = u
lon2, lat2 = v
distance = haversine(lon1, lat1, lon2, lat2)
distance = haversine(u[0], u[1], v[0], v[1])
self.final_mst[u][v]['weight'] = distance
except Exception as e:
logging.error(f"Error converting edge weights to meters: {e}")
raise
def _create_final_network_graph(self):
"""
Create the final network graph with the required attributes from the final MST.
"""
self.network_graph = nx.Graph()
node_id = 1
node_mapping = {}
for node in self.final_mst.nodes:
pos = node
if 'type' in self.final_mst.nodes[node]:
if self.final_mst.nodes[node]['type'] == 'building':
name = self.final_mst.nodes[node]['name']
node_type = 'building'
elif self.final_mst.nodes[node]['type'] == 'generation':
name = self.final_mst.nodes[node]['name']
node_type = 'generation'
else:
name = f'junction_{node_id}'
node_type = 'junction'
self.network_graph.add_node(node_id, name=name, type=node_type, pos=pos)
node_mapping[node] = node_id
node_id += 1
for u, v, data in self.final_mst.edges(data=True):
u_new = node_mapping[u]
v_new = node_mapping[v]
length = data['weight']
self.network_graph.add_edge(u_new, v_new, length=length)
def plot_network_graph(self):
"""
Plot the network graph using matplotlib and networkx.
"""
plt.figure(figsize=(15, 10))
pos = {node: (node[0], node[1]) for node in self.final_mst.nodes()}
nx.draw_networkx_nodes(self.final_mst, pos, node_color='blue', node_size=50)
nx.draw_networkx_edges(self.final_mst, pos, edge_color='gray')
pos = {node: data['pos'] for node, data in self.network_graph.nodes(data=True)}
nx.draw_networkx_nodes(self.network_graph, pos, node_color='blue', node_size=50)
nx.draw_networkx_edges(self.network_graph, pos, edge_color='gray')
plt.title('District Heating Network Graph')
plt.axis('off')
plt.show()

View File

@ -1,54 +0,0 @@
import json
from shapely import LineString, Point
import networkx as nx
from pathlib import Path
def networkx_to_geojson(graph: nx.Graph) -> Path:
"""
Convert a NetworkX graph to GeoJSON format.
:param graph: A NetworkX graph.
:return: GeoJSON formatted dictionary.
"""
features = []
for u, v, data in graph.edges(data=True):
line = LineString([u, v])
feature = {
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": list(line.coords)
},
"properties": {
"weight": data.get("weight", 1.0)
}
}
features.append(feature)
for node, data in graph.nodes(data=True):
point = Point(node)
feature = {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": list(point.coords)[0]
},
"properties": {
"type": data.get("type", "unknown"),
"id": data.get("id", "N/A")
}
}
features.append(feature)
geojson = {
"type": "FeatureCollection",
"features": features
}
output_geojson_file = Path('./out_files/network_graph.geojson').resolve()
with open(output_geojson_file, 'w') as file:
json.dump(geojson, file, indent=4)
return output_geojson_file

View File

@ -1,80 +0,0 @@
import pandas as pd
import numpy as np
class DemandShiftProcessor:
def __init__(self, city):
self.city = city
def random_shift(self, series):
shift_amount = np.random.randint(0, round(0.005 * len(series)))
return series.shift(shift_amount).fillna(series.shift(shift_amount - len(series)))
def process_demands(self):
heating_dfs = []
cooling_dfs = []
for building in self.city.buildings:
heating_df = self.convert_building_to_dataframe(building, 'heating')
cooling_df = self.convert_building_to_dataframe(building, 'cooling')
heating_df.set_index('Date/Time', inplace=True)
cooling_df.set_index('Date/Time', inplace=True)
shifted_heating_demands = heating_df.apply(self.random_shift, axis=0)
shifted_cooling_demands = cooling_df.apply(self.random_shift, axis=0)
self.update_building_demands(building, shifted_heating_demands, 'heating')
self.update_building_demands(building, shifted_cooling_demands, 'cooling')
heating_dfs.append(shifted_heating_demands)
cooling_dfs.append(shifted_cooling_demands)
combined_heating_df = pd.concat(heating_dfs, axis=1)
combined_cooling_df = pd.concat(cooling_dfs, axis=1)
self.calculate_and_set_simultaneity_factor(combined_heating_df, 'heating')
self.calculate_and_set_simultaneity_factor(combined_cooling_df, 'cooling')
def convert_building_to_dataframe(self, building, demand_type):
if demand_type == 'heating':
data = {
"Date/Time": self.generate_date_time_index(),
"Heating_Demand": building.heating_demand["hour"]
}
else: # cooling
data = {
"Date/Time": self.generate_date_time_index(),
"Cooling_Demand": building.cooling_demand["hour"]
}
return pd.DataFrame(data)
def generate_date_time_index(self):
# Generate hourly date time index for a full year in 2024
date_range = pd.date_range(start="2013-01-01 00:00:00", end="2013-12-31 23:00:00", freq='H')
return date_range.strftime('%m/%d %H:%M:%S').tolist()
def update_building_demands(self, building, shifted_demands, demand_type):
if demand_type == 'heating':
shifted_series = shifted_demands["Heating_Demand"]
building.heating_demand = self.calculate_new_demands(shifted_series)
else: # cooling
shifted_series = shifted_demands["Cooling_Demand"]
building.cooling_demand = self.calculate_new_demands(shifted_series)
def calculate_new_demands(self, shifted_series):
new_demand = {
"hour": shifted_series.tolist(),
"month": self.calculate_monthly_demand(shifted_series),
"year": [shifted_series.sum()]
}
return new_demand
def calculate_monthly_demand(self, series):
series.index = pd.to_datetime(series.index, format='%m/%d %H:%M:%S')
monthly_demand = series.resample('M').sum()
return monthly_demand.tolist()
def calculate_and_set_simultaneity_factor(self, combined_df, demand_type):
total_demand_original = combined_df.sum(axis=1)
peak_total_demand_original = total_demand_original.max()
individual_peak_demands = combined_df.max(axis=0)
sum_individual_peak_demands = individual_peak_demands.sum()
if demand_type == 'heating':
self.city.simultaneity_factor_heating = peak_total_demand_original / sum_individual_peak_demands
else: # cooling
self.city.simultaneity_factor_cooling = peak_total_demand_original / sum_individual_peak_demands

View File

@ -1,54 +0,0 @@
from pathlib import Path
import subprocess
from scripts.ep_run_enrich import energy_plus_workflow
from hub.imports.geometry_factory import GeometryFactory
from hub.helpers.dictionaries import Dictionaries
from hub.imports.construction_factory import ConstructionFactory
from hub.imports.usage_factory import UsageFactory
from hub.imports.weather_factory import WeatherFactory
from hub.imports.results_factory import ResultFactory
from scripts.energy_system_retrofit_report import EnergySystemRetrofitReport
from scripts.geojson_creator import process_geojson
from scripts import random_assignation
from hub.imports.energy_systems_factory import EnergySystemsFactory
from scripts.energy_system_sizing import SystemSizing
from scripts.solar_angles import CitySolarAngles
from scripts.pv_sizing_and_simulation import PVSizingSimulation
from scripts.energy_system_retrofit_results import consumption_data, cost_data
from scripts.energy_system_sizing_and_simulation_factory import EnergySystemsSimulationFactory
from scripts.costs.cost import Cost
from scripts.costs.constants import SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV, SYSTEM_RETROFIT_AND_PV, CURRENT_STATUS
import hub.helpers.constants as cte
from hub.exports.exports_factory import ExportsFactory
from scripts.pv_feasibility import pv_feasibility
# Specify the GeoJSON file path
input_files_path = (Path(__file__).parent / 'input_files')
input_files_path.mkdir(parents=True, exist_ok=True)
geojson_file = process_geojson(x=-73.5681295982132, y=45.49218262677643, diff=0.0001)
geojson_file_path = input_files_path / 'output_buildings.geojson'
output_path = (Path(__file__).parent / 'out_files').resolve()
output_path.mkdir(parents=True, exist_ok=True)
energy_plus_output_path = output_path / 'energy_plus_outputs'
energy_plus_output_path.mkdir(parents=True, exist_ok=True)
simulation_results_path = (Path(__file__).parent / 'out_files' / 'simulation_results').resolve()
simulation_results_path.mkdir(parents=True, exist_ok=True)
sra_output_path = output_path / 'sra_outputs'
sra_output_path.mkdir(parents=True, exist_ok=True)
cost_analysis_output_path = output_path / 'cost_analysis'
cost_analysis_output_path.mkdir(parents=True, exist_ok=True)
city = GeometryFactory(file_type='geojson',
path=geojson_file_path,
height_field='height',
year_of_construction_field='year_of_construction',
function_field='function',
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
ConstructionFactory('nrcan', city).enrich()
UsageFactory('nrcan', city).enrich()
WeatherFactory('epw', city).enrich()
energy_plus_workflow(city, energy_plus_output_path)
random_assignation.call_random(city.buildings, random_assignation.residential_new_systems_percentage)
EnergySystemsFactory('montreal_future', city).enrich()
for building in city.buildings:
EnergySystemsSimulationFactory('archetype1', building=building, output_path=simulation_results_path).enrich()

View File

@ -1,675 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"id": "initial_id",
"metadata": {
"collapsed": true,
"ExecuteTime": {
"end_time": "2024-07-31T21:38:47.230085Z",
"start_time": "2024-07-31T21:38:47.206748Z"
}
},
"source": [
"from pathlib import Path\n",
"from scripts.district_heating_network.directory_manager import DirectoryManager\n",
"import subprocess\n",
"from scripts.ep_run_enrich import energy_plus_workflow\n",
"from hub.imports.geometry_factory import GeometryFactory\n",
"from hub.helpers.dictionaries import Dictionaries\n",
"from hub.imports.construction_factory import ConstructionFactory\n",
"from hub.imports.usage_factory import UsageFactory\n",
"from hub.imports.weather_factory import WeatherFactory\n",
"from hub.imports.results_factory import ResultFactory\n",
"from scripts.energy_system_retrofit_report import EnergySystemRetrofitReport\n",
"from scripts.geojson_creator import process_geojson\n",
"from scripts import random_assignation\n",
"from hub.imports.energy_systems_factory import EnergySystemsFactory\n",
"from scripts.energy_system_sizing import SystemSizing\n",
"from scripts.solar_angles import CitySolarAngles\n",
"from scripts.pv_sizing_and_simulation import PVSizingSimulation\n",
"from scripts.energy_system_retrofit_results import consumption_data, cost_data\n",
"from scripts.energy_system_sizing_and_simulation_factory import EnergySystemsSimulationFactory\n",
"from scripts.costs.cost import Cost\n",
"from scripts.costs.constants import SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV, SYSTEM_RETROFIT_AND_PV, CURRENT_STATUS\n",
"import hub.helpers.constants as cte\n",
"from hub.exports.exports_factory import ExportsFactory\n",
"from scripts.pv_feasibility import pv_feasibility\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np"
],
"outputs": [],
"execution_count": 110
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-07-31T21:38:47.861524Z",
"start_time": "2024-07-31T21:38:47.843529Z"
}
},
"cell_type": "code",
"source": [
"base_path = \"./\"\n",
"dir_manager = DirectoryManager(base_path)\n",
"\n",
"# Input files directory\n",
"input_files_path = dir_manager.create_directory('input_files')\n",
"geojson_file_path = input_files_path / 'output_buildings.geojson'\n",
"\n",
"# Output files directory\n",
"output_path = dir_manager.create_directory('out_files')\n",
"\n",
"# Subdirectories for output files\n",
"energy_plus_output_path = dir_manager.create_directory('out_files/energy_plus_outputs')\n",
"simulation_results_path = dir_manager.create_directory('out_files/simulation_results')\n",
"sra_output_path = dir_manager.create_directory('out_files/sra_outputs')\n",
"cost_analysis_output_path = dir_manager.create_directory('out_files/cost_analysis')"
],
"id": "7d895f0e4ec2b851",
"outputs": [],
"execution_count": 111
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-07-31T21:39:02.661096Z",
"start_time": "2024-07-31T21:38:48.727802Z"
}
},
"cell_type": "code",
"source": [
"location = [45.53067276979674, -73.70234652694087]\n",
"process_geojson(x=location[1], y=location[0], diff=0.001)"
],
"id": "20dfb8fa42189fc2",
"outputs": [
{
"data": {
"text/plain": [
"WindowsPath('C:/Users/ab_reza/Majid/Concordia/Repositories/energy_system_modelling_workflow/input_files/output_buildings.geojson')"
]
},
"execution_count": 112,
"metadata": {},
"output_type": "execute_result"
}
],
"execution_count": 112
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-07-31T21:39:02.992446Z",
"start_time": "2024-07-31T21:39:02.663422Z"
}
},
"cell_type": "code",
"source": [
"city = GeometryFactory(file_type='geojson',\n",
" path=geojson_file_path,\n",
" height_field='height',\n",
" year_of_construction_field='year_of_construction',\n",
" function_field='function',\n",
" function_to_hub=Dictionaries().montreal_function_to_hub_function).city"
],
"id": "c03ae7cae09d4b21",
"outputs": [],
"execution_count": 113
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-07-31T21:39:03.340164Z",
"start_time": "2024-07-31T21:39:02.993466Z"
}
},
"cell_type": "code",
"source": "ConstructionFactory('nrcan', city).enrich()",
"id": "c7d73638802e40d9",
"outputs": [],
"execution_count": 114
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-07-31T21:39:04.079698Z",
"start_time": "2024-07-31T21:39:03.342163Z"
}
},
"cell_type": "code",
"source": "UsageFactory('nrcan', city).enrich()",
"id": "4a8e272413233cc9",
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"C:\\Users\\ab_reza\\Majid\\Concordia\\Repositories\\energy_system_modelling_workflow\\hub\\catalog_factories\\usage\\comnet_catalog.py:193: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`\n",
" usage_type = usage_parameters[0]\n"
]
}
],
"execution_count": 115
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-07-31T21:39:04.648022Z",
"start_time": "2024-07-31T21:39:04.081700Z"
}
},
"cell_type": "code",
"source": "WeatherFactory('epw', city).enrich()",
"id": "f66c01cb42c33b64",
"outputs": [],
"execution_count": 116
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-07-31T21:40:39.688386Z",
"start_time": "2024-07-31T21:39:04.650024Z"
}
},
"cell_type": "code",
"source": "energy_plus_workflow(city, energy_plus_output_path)",
"id": "c966b769566c173b",
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"exporting:\n",
" idf exported...\n",
"\r\n",
"C:/EnergyPlusV23-2-0\\energyplus.exe --weather C:\\Users\\ab_reza\\Majid\\Concordia\\Repositories\\energy_system_modelling_workflow\\hub\\data\\weather\\epw\\CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw --output-directory C:\\Users\\ab_reza\\Majid\\Concordia\\Repositories\\energy_system_modelling_workflow\\out_files\\energy_plus_outputs --idd C:\\Users\\ab_reza\\Majid\\Concordia\\Repositories\\energy_system_modelling_workflow\\hub\\exports\\building_energy\\idf_files\\Energy+.idd --expandobjects --readvars --output-prefix Laval_ C:\\Users\\ab_reza\\Majid\\Concordia\\Repositories\\energy_system_modelling_workflow\\out_files\\energy_plus_outputs\\Laval_602570.idf\r\n",
"\n"
]
}
],
"execution_count": 117
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-07-31T21:53:14.440222Z",
"start_time": "2024-07-31T21:53:10.290860Z"
}
},
"cell_type": "code",
"source": [
"from scripts.district_heating_network.district_heating_network_creator import DistrictHeatingNetworkCreator\n",
"from scripts.district_heating_network.road_processor import road_processor\n",
"from pathlib import Path\n",
"import time\n",
"from scripts.district_heating_network.geojson_graph_creator import networkx_to_geojson\n",
"roads_file = road_processor(location[1], location[0], 0.001)\n",
"\n",
"dhn_creator = DistrictHeatingNetworkCreator(geojson_file_path, roads_file)\n",
"\n",
"network_graph = dhn_creator.run()"
],
"id": "8403846b0831b51d",
"outputs": [
{
"ename": "AttributeError",
"evalue": "'Graph' object has no attribute 'building_names'",
"output_type": "error",
"traceback": [
"\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
"\u001B[1;31mAttributeError\u001B[0m Traceback (most recent call last)",
"Cell \u001B[1;32mIn[121], line 11\u001B[0m\n\u001B[0;32m 8\u001B[0m dhn_creator \u001B[38;5;241m=\u001B[39m DistrictHeatingNetworkCreator(geojson_file_path, roads_file)\n\u001B[0;32m 10\u001B[0m network_graph \u001B[38;5;241m=\u001B[39m dhn_creator\u001B[38;5;241m.\u001B[39mrun()\n\u001B[1;32m---> 11\u001B[0m \u001B[43mnetwork_graph\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mbuilding_names\u001B[49m\n",
"\u001B[1;31mAttributeError\u001B[0m: 'Graph' object has no attribute 'building_names'"
]
}
],
"execution_count": 121
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-07-31T21:43:05.521839Z",
"start_time": "2024-07-31T21:43:05.503748Z"
}
},
"cell_type": "code",
"source": [
"for node_id, attrs in network_graph.nodes(data=True):\n",
" print(f\"Node {node_id} has attributes: {list(attrs.keys())}\")"
],
"id": "9c4c32ed4a5b5434",
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Node (-73.70263014634182, 45.52966550204674) has attributes: []\n",
"Node (-73.70252245592799, 45.52959782722166) has attributes: []\n",
"Node (-73.70277983402246, 45.52975956880018) has attributes: []\n",
"Node (-73.70292834674622, 45.52985289718704) has attributes: []\n",
"Node (-73.70299601156968, 45.52989541912497) has attributes: []\n",
"Node (-73.70304798829301, 45.52992808234479) has attributes: []\n",
"Node (-73.70315317772048, 45.52999418549968) has attributes: []\n",
"Node (-73.70322951375971, 45.530042156604246) has attributes: []\n",
"Node (-73.70334527410391, 45.53011490273612) has attributes: []\n",
"Node (-73.70388612860485, 45.530454786598085) has attributes: []\n",
"Node (-73.70321670301797, 45.53098320823811) has attributes: []\n",
"Node (-73.70309371940914, 45.53090572804479) has attributes: []\n",
"Node (-73.70336752508702, 45.53107818505422) has attributes: []\n",
"Node (-73.70300302780161, 45.53115122842582) has attributes: []\n",
"Node (-73.70298632291501, 45.53083806779961) has attributes: []\n",
"Node (-73.70284664272657, 45.53075006869057) has attributes: []\n",
"Node (-73.70282694240179, 45.530737657402696) has attributes: []\n",
"Node (-73.70268296446567, 45.530646950694454) has attributes: []\n",
"Node (-73.70262035905371, 45.53060750902034) has attributes: []\n",
"Node (-73.70250974072788, 45.53053781900757) has attributes: []\n",
"Node (-73.70248122664219, 45.530519855013075) has attributes: []\n",
"Node (-73.70237692791034, 45.53045414637121) has attributes: []\n",
"Node (-73.70241425825014, 45.52952983362164) has attributes: []\n",
"Node (-73.70258909924681, 45.53147671471601) has attributes: []\n",
"Node (-73.70246956317335, 45.531401341489406) has attributes: []\n",
"Node (-73.70281850395438, 45.53162108764596) has attributes: []\n",
"Node (-73.70235595692806, 45.53165968576366) has attributes: []\n",
"Node (-73.70235908646175, 45.53133168062488) has attributes: []\n",
"Node (-73.70226538550632, 45.5312725976791) has attributes: []\n",
"Node (-73.7022262934011, 45.531247948232114) has attributes: []\n",
"Node (-73.70218216283965, 45.53122012179686) has attributes: []\n",
"Node (-73.7020876584622, 45.53116053225497) has attributes: []\n",
"Node (-73.70208089954498, 45.53115627043355) has attributes: []\n",
"Node (-73.70195718026818, 45.531078259496624) has attributes: []\n",
"Node (-73.7019336727694, 45.53106343689135) has attributes: []\n",
"Node (-73.70183972286668, 45.53100419697237) has attributes: []\n",
"Node (-73.70182154258106, 45.53099273343045) has attributes: []\n",
"Node (-73.70170504466955, 45.530919275910655) has attributes: []\n",
"Node (-73.70169068527439, 45.5309102216234) has attributes: []\n",
"Node (-73.70191018896638, 45.53200952628766) has attributes: []\n",
"Node (-73.70343390828414, 45.5311199883841) has attributes: []\n",
"Node (-73.70308928370066, 45.53179149942939) has attributes: []\n",
"Node (-73.70154615235963, 45.53081908668964) has attributes: []\n",
"Node (-73.70149535566978, 45.53078705694076) has attributes: []\n",
"Node (-73.70139243548935, 45.530722160831516) has attributes: []\n",
"Node (-73.70235555653572, 45.5304406823149) has attributes: []\n",
"Node (-73.70223631048641, 45.530365556799865) has attributes: []\n",
"Node (-73.70218808966641, 45.53033517747947) has attributes: []\n",
"Node (-73.7020516180255, 45.53024919976893) has attributes: []\n",
"Node (-73.70202483520858, 45.530232326481084) has attributes: []\n",
"Node (-73.70189576536478, 45.53015101193401) has attributes: []\n",
"Node (-73.70188535693748, 45.53014445458083) has attributes: []\n",
"Node (-73.70176137113975, 45.53006634300427) has attributes: []\n",
"Node (-73.70171679336974, 45.53003825882077) has attributes: []\n",
"Node (-73.70161674578377, 45.52997522841877) has attributes: []\n",
"Node (-73.70157021391765, 45.52994591314646) has attributes: []\n",
"Node (-73.70145508528618, 45.52987338162208) has attributes: []\n",
"Node (-73.7015262783945, 45.53176766055835) has attributes: []\n",
"Node (-73.70142255824699, 45.531702316306436) has attributes: []\n",
"Node (-73.70132694890151, 45.53164208190352) has attributes: []\n",
"Node (-73.70249378379357, 45.529882494691094) has attributes: ['type', 'id']\n",
"Node (-73.70236957992, 45.530697070843594) has attributes: ['type', 'id']\n",
"Node (-73.7023772579133, 45.52982887967387) has attributes: ['type', 'id']\n",
"Node (-73.70310348189996, 45.530242710105696) has attributes: ['type', 'id']\n",
"Node (-73.70219141578475, 45.5309810002753) has attributes: ['type', 'id']\n",
"Node (-73.7015878987858, 45.53110506016847) has attributes: ['type', 'id']\n",
"Node (-73.70197756808213, 45.531335127032875) has attributes: ['type', 'id']\n",
"Node (-73.70171824652937, 45.53119684899265) has attributes: ['type', 'id']\n",
"Node (-73.70181225980849, 45.53125598840158) has attributes: ['type', 'id']\n",
"Node (-73.70212216033907, 45.53141309516707) has attributes: ['type', 'id']\n",
"Node (-73.70224797036111, 45.531522088920134) has attributes: ['type', 'id']\n",
"Node (-73.70319066728962, 45.53075184355254) has attributes: ['type', 'id']\n",
"Node (-73.70309318391786, 45.53066844829803) has attributes: ['type', 'id']\n",
"Node (-73.70326346262547, 45.53124343502157) has attributes: ['type', 'id']\n",
"Node (-73.70289161913149, 45.53100954740511) has attributes: ['type', 'id']\n",
"Node (-73.7031243168426, 45.52969124795911) has attributes: ['type', 'id']\n",
"Node (-73.70332165936908, 45.531298238343524) has attributes: ['type', 'id']\n",
"Node (-73.70291683392738, 45.531464843960194) has attributes: ['type', 'id']\n",
"Node (-73.70257423757026, 45.53123533603945) has attributes: ['type', 'id']\n",
"Node (-73.70246354979903, 45.53116600989907) has attributes: ['type', 'id']\n",
"Node (-73.70137270924536, 45.53098156462814) has attributes: ['type', 'id']\n",
"Node (-73.70228611728258, 45.52973374332967) has attributes: ['type', 'id']\n",
"Node (-73.70192277090158, 45.530832193189546) has attributes: ['type', 'id']\n",
"Node (-73.70247403248253, 45.530300013163604) has attributes: ['type', 'id']\n",
"Node (-73.70233258364674, 45.53021274328478) has attributes: ['type', 'id']\n",
"Node (-73.70150159992788, 45.530157998392504) has attributes: ['type', 'id']\n",
"Node (-73.70178207574742, 45.53033147043354) has attributes: ['type', 'id']\n",
"Node (-73.70279118480165, 45.53007116190442) has attributes: ['type', 'id']\n",
"Node (-73.70290386342012, 45.53015742711493) has attributes: ['type', 'id']\n",
"Node (-73.70199360008198, 45.529972641218336) has attributes: ['type', 'id']\n",
"Node (-73.7032815855412, 45.52978985115031) has attributes: ['type', 'id']\n",
"Node (-73.70166271484868, 45.53063422765041) has attributes: ['type', 'id']\n",
"Node (-73.7015006171488, 45.530550593136034) has attributes: ['type', 'id']\n",
"Node (-73.70265213028476, 45.529962782747816) has attributes: ['type', 'id']\n",
"Node (-73.7029326957311, 45.53056979610127) has attributes: ['type', 'id']\n",
"Node (-73.70166661687237, 45.5297928936099) has attributes: ['type', 'id']\n",
"Node (-73.70193452736822, 45.53043505670828) has attributes: ['type', 'id']\n",
"Node (-73.70320906423977, 45.53033165241546) has attributes: ['type', 'id']\n",
"Node (-73.70242433058544, 45.531020523149344) has attributes: ['type', 'id']\n",
"Node (-73.70229173916934, 45.53104634226288) has attributes: ['type', 'id']\n",
"Node (-73.70164581777142, 45.53024975981883) has attributes: ['type', 'id']\n",
"Node (-73.70181323564402, 45.52988517687263) has attributes: ['type', 'id']\n",
"Node (-73.70207977647193, 45.53050710203167) has attributes: ['type', 'id']\n",
"Node (-73.70180201572698, 45.53073366018695) has attributes: ['type', 'id']\n",
"Node (-73.70260551746348, 45.53038579346295) has attributes: ['type', 'id']\n",
"Node (-73.7015368490746, 45.531520903846236) has attributes: ['type', 'id']\n",
"Node (-73.70277909755795, 45.530494359508104) has attributes: ['type', 'id']\n",
"Node (-73.7016306503588, 45.531601992190964) has attributes: ['type', 'id']\n",
"Node (-73.703188128229, 45.531634438129004) has attributes: ['type', 'id']\n",
"Node (-73.70225201894137, 45.5306050266003) has attributes: ['type', 'id']\n",
"Node (-73.70250211711432, 45.53079519337939) has attributes: ['type', 'id']\n",
"Node (-73.70143287673753, 45.53147394391961) has attributes: ['type', 'id']\n",
"Node (-73.7015564456529, 45.52971249323039) has attributes: ['type', 'id']\n",
"Node (-73.70213321668199, 45.530060293550356) has attributes: ['type', 'id']\n",
"Node (-73.70205098392802, 45.53092949418992) has attributes: ['type', 'id']\n",
"Node (-73.70273955351598, 45.53092005042424) has attributes: ['type', 'id']\n"
]
}
],
"execution_count": 119
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-07-31T21:29:21.717811Z",
"start_time": "2024-07-31T21:29:21.697811Z"
}
},
"cell_type": "code",
"source": [
"from scripts.district_heating_network.district_heating_factory import DistrictHeatingFactory\n",
"\n",
"DistrictHeatingFactory(city=city, graph=network_graph)"
],
"id": "25e14bd5433e3d95",
"outputs": [
{
"ename": "TypeError",
"evalue": "__init__() got an unexpected keyword argument 'graph'",
"output_type": "error",
"traceback": [
"\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
"\u001B[1;31mTypeError\u001B[0m Traceback (most recent call last)",
"Cell \u001B[1;32mIn[94], line 3\u001B[0m\n\u001B[0;32m 1\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01mscripts\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mdistrict_heating_network\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mdistrict_heating_factory\u001B[39;00m \u001B[38;5;28;01mimport\u001B[39;00m DistrictHeatingFactory\n\u001B[1;32m----> 3\u001B[0m \u001B[43mDistrictHeatingFactory\u001B[49m\u001B[43m(\u001B[49m\u001B[43mcity\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mcity\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mgraph\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mnetwork_graph\u001B[49m\u001B[43m)\u001B[49m\n",
"\u001B[1;31mTypeError\u001B[0m: __init__() got an unexpected keyword argument 'graph'"
]
}
],
"execution_count": 94
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-07-31T21:18:46.818842Z",
"start_time": "2024-07-31T21:18:46.799573Z"
}
},
"cell_type": "code",
"source": [
"for node_id, attrs in network_graph.nodes(data=True):\n",
" print(f\"Node {node_id} has attributes: {list(attrs.keys())}\")"
],
"id": "ad48fbc87a598b85",
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Node (-73.70263014634182, 45.52966550204674) has attributes: []\n",
"Node (-73.70252245592799, 45.52959782722166) has attributes: []\n",
"Node (-73.70277983402246, 45.52975956880018) has attributes: []\n",
"Node (-73.70292834674622, 45.52985289718704) has attributes: []\n",
"Node (-73.70299601156968, 45.52989541912497) has attributes: []\n",
"Node (-73.70304798829301, 45.52992808234479) has attributes: []\n",
"Node (-73.70315317772048, 45.52999418549968) has attributes: []\n",
"Node (-73.70322951375971, 45.530042156604246) has attributes: []\n",
"Node (-73.70334527410391, 45.53011490273612) has attributes: []\n",
"Node (-73.70388612860485, 45.530454786598085) has attributes: []\n",
"Node (-73.70321670301797, 45.53098320823811) has attributes: []\n",
"Node (-73.70309371940914, 45.53090572804479) has attributes: []\n",
"Node (-73.70336752508702, 45.53107818505422) has attributes: []\n",
"Node (-73.70300302780161, 45.53115122842582) has attributes: []\n",
"Node (-73.70298632291501, 45.53083806779961) has attributes: []\n",
"Node (-73.70284664272657, 45.53075006869057) has attributes: []\n",
"Node (-73.70282694240179, 45.530737657402696) has attributes: []\n",
"Node (-73.70268296446567, 45.530646950694454) has attributes: []\n",
"Node (-73.70262035905371, 45.53060750902034) has attributes: []\n",
"Node (-73.70250974072788, 45.53053781900757) has attributes: []\n",
"Node (-73.70248122664219, 45.530519855013075) has attributes: []\n",
"Node (-73.70237692791034, 45.53045414637121) has attributes: []\n",
"Node (-73.70241425825014, 45.52952983362164) has attributes: []\n",
"Node (-73.70258909924681, 45.53147671471601) has attributes: []\n",
"Node (-73.70246956317335, 45.531401341489406) has attributes: []\n",
"Node (-73.70281850395438, 45.53162108764596) has attributes: []\n",
"Node (-73.70235595692806, 45.53165968576366) has attributes: []\n",
"Node (-73.70235908646175, 45.53133168062488) has attributes: []\n",
"Node (-73.70226538550632, 45.5312725976791) has attributes: []\n",
"Node (-73.7022262934011, 45.531247948232114) has attributes: []\n",
"Node (-73.70218216283965, 45.53122012179686) has attributes: []\n",
"Node (-73.7020876584622, 45.53116053225497) has attributes: []\n",
"Node (-73.70208089954498, 45.53115627043355) has attributes: []\n",
"Node (-73.70195718026818, 45.531078259496624) has attributes: []\n",
"Node (-73.7019336727694, 45.53106343689135) has attributes: []\n",
"Node (-73.70183972286668, 45.53100419697237) has attributes: []\n",
"Node (-73.70182154258106, 45.53099273343045) has attributes: []\n",
"Node (-73.70170504466955, 45.530919275910655) has attributes: []\n",
"Node (-73.70169068527439, 45.5309102216234) has attributes: []\n",
"Node (-73.70191018896638, 45.53200952628766) has attributes: []\n",
"Node (-73.70343390828414, 45.5311199883841) has attributes: []\n",
"Node (-73.70308928370066, 45.53179149942939) has attributes: []\n",
"Node (-73.70154615235963, 45.53081908668964) has attributes: []\n",
"Node (-73.70149535566978, 45.53078705694076) has attributes: []\n",
"Node (-73.70139243548935, 45.530722160831516) has attributes: []\n",
"Node (-73.70235555653572, 45.5304406823149) has attributes: []\n",
"Node (-73.70223631048641, 45.530365556799865) has attributes: []\n",
"Node (-73.70218808966641, 45.53033517747947) has attributes: []\n",
"Node (-73.7020516180255, 45.53024919976893) has attributes: []\n",
"Node (-73.70202483520858, 45.530232326481084) has attributes: []\n",
"Node (-73.70189576536478, 45.53015101193401) has attributes: []\n",
"Node (-73.70188535693748, 45.53014445458083) has attributes: []\n",
"Node (-73.70176137113975, 45.53006634300427) has attributes: []\n",
"Node (-73.70171679336974, 45.53003825882077) has attributes: []\n",
"Node (-73.70161674578377, 45.52997522841877) has attributes: []\n",
"Node (-73.70157021391765, 45.52994591314646) has attributes: []\n",
"Node (-73.70145508528618, 45.52987338162208) has attributes: []\n",
"Node (-73.7015262783945, 45.53176766055835) has attributes: []\n",
"Node (-73.70142255824699, 45.531702316306436) has attributes: []\n",
"Node (-73.70132694890151, 45.53164208190352) has attributes: []\n",
"Node (-73.70249378379357, 45.529882494691094) has attributes: ['type', 'id']\n",
"Node (-73.70236957992, 45.530697070843594) has attributes: ['type', 'id']\n",
"Node (-73.7023772579133, 45.52982887967387) has attributes: ['type', 'id']\n",
"Node (-73.70310348189996, 45.530242710105696) has attributes: ['type', 'id']\n",
"Node (-73.70219141578475, 45.5309810002753) has attributes: ['type', 'id']\n",
"Node (-73.7015878987858, 45.53110506016847) has attributes: ['type', 'id']\n",
"Node (-73.70197756808213, 45.531335127032875) has attributes: ['type', 'id']\n",
"Node (-73.70171824652937, 45.53119684899265) has attributes: ['type', 'id']\n",
"Node (-73.70181225980849, 45.53125598840158) has attributes: ['type', 'id']\n",
"Node (-73.70212216033907, 45.53141309516707) has attributes: ['type', 'id']\n",
"Node (-73.70224797036111, 45.531522088920134) has attributes: ['type', 'id']\n",
"Node (-73.70319066728962, 45.53075184355254) has attributes: ['type', 'id']\n",
"Node (-73.70309318391786, 45.53066844829803) has attributes: ['type', 'id']\n",
"Node (-73.70326346262547, 45.53124343502157) has attributes: ['type', 'id']\n",
"Node (-73.70289161913149, 45.53100954740511) has attributes: ['type', 'id']\n",
"Node (-73.7031243168426, 45.52969124795911) has attributes: ['type', 'id']\n",
"Node (-73.70332165936908, 45.531298238343524) has attributes: ['type', 'id']\n",
"Node (-73.70291683392738, 45.531464843960194) has attributes: ['type', 'id']\n",
"Node (-73.70257423757026, 45.53123533603945) has attributes: ['type', 'id']\n",
"Node (-73.70246354979903, 45.53116600989907) has attributes: ['type', 'id']\n",
"Node (-73.70137270924536, 45.53098156462814) has attributes: ['type', 'id']\n",
"Node (-73.70228611728258, 45.52973374332967) has attributes: ['type', 'id']\n",
"Node (-73.70192277090158, 45.530832193189546) has attributes: ['type', 'id']\n",
"Node (-73.70247403248253, 45.530300013163604) has attributes: ['type', 'id']\n",
"Node (-73.70233258364674, 45.53021274328478) has attributes: ['type', 'id']\n",
"Node (-73.70150159992788, 45.530157998392504) has attributes: ['type', 'id']\n",
"Node (-73.70178207574742, 45.53033147043354) has attributes: ['type', 'id']\n",
"Node (-73.70279118480165, 45.53007116190442) has attributes: ['type', 'id']\n",
"Node (-73.70290386342012, 45.53015742711493) has attributes: ['type', 'id']\n",
"Node (-73.70199360008198, 45.529972641218336) has attributes: ['type', 'id']\n",
"Node (-73.7032815855412, 45.52978985115031) has attributes: ['type', 'id']\n",
"Node (-73.70166271484868, 45.53063422765041) has attributes: ['type', 'id']\n",
"Node (-73.7015006171488, 45.530550593136034) has attributes: ['type', 'id']\n",
"Node (-73.70265213028476, 45.529962782747816) has attributes: ['type', 'id']\n",
"Node (-73.7029326957311, 45.53056979610127) has attributes: ['type', 'id']\n",
"Node (-73.70166661687237, 45.5297928936099) has attributes: ['type', 'id']\n",
"Node (-73.70193452736822, 45.53043505670828) has attributes: ['type', 'id']\n",
"Node (-73.70320906423977, 45.53033165241546) has attributes: ['type', 'id']\n",
"Node (-73.70242433058544, 45.531020523149344) has attributes: ['type', 'id']\n",
"Node (-73.70229173916934, 45.53104634226288) has attributes: ['type', 'id']\n",
"Node (-73.70164581777142, 45.53024975981883) has attributes: ['type', 'id']\n",
"Node (-73.70181323564402, 45.52988517687263) has attributes: ['type', 'id']\n",
"Node (-73.70207977647193, 45.53050710203167) has attributes: ['type', 'id']\n",
"Node (-73.70180201572698, 45.53073366018695) has attributes: ['type', 'id']\n",
"Node (-73.70260551746348, 45.53038579346295) has attributes: ['type', 'id']\n",
"Node (-73.7015368490746, 45.531520903846236) has attributes: ['type', 'id']\n",
"Node (-73.70277909755795, 45.530494359508104) has attributes: ['type', 'id']\n",
"Node (-73.7016306503588, 45.531601992190964) has attributes: ['type', 'id']\n",
"Node (-73.703188128229, 45.531634438129004) has attributes: ['type', 'id']\n",
"Node (-73.70225201894137, 45.5306050266003) has attributes: ['type', 'id']\n",
"Node (-73.70250211711432, 45.53079519337939) has attributes: ['type', 'id']\n",
"Node (-73.70143287673753, 45.53147394391961) has attributes: ['type', 'id']\n",
"Node (-73.7015564456529, 45.52971249323039) has attributes: ['type', 'id']\n",
"Node (-73.70213321668199, 45.530060293550356) has attributes: ['type', 'id']\n",
"Node (-73.70205098392802, 45.53092949418992) has attributes: ['type', 'id']\n",
"Node (-73.70273955351598, 45.53092005042424) has attributes: ['type', 'id']\n"
]
}
],
"execution_count": 80
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-07-31T20:23:57.446448Z",
"start_time": "2024-07-31T20:23:57.431469Z"
}
},
"cell_type": "code",
"source": [
"for building in city.buildings:\n",
" print(building.name)"
],
"id": "5b96a042e349e0eb",
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"65418\n",
"70816\n",
"73478\n",
"82649\n",
"84906\n",
"87241\n",
"87719\n",
"88675\n",
"88747\n",
"89061\n",
"89062\n",
"89251\n",
"91214\n",
"92337\n",
"92399\n",
"92520\n",
"92979\n",
"93149\n",
"95265\n",
"95266\n",
"95465\n",
"95704\n",
"96241\n",
"96579\n",
"96580\n",
"96930\n",
"96931\n",
"96996\n",
"96997\n",
"97648\n",
"98087\n",
"98666\n",
"98667\n",
"102035\n",
"103043\n",
"103740\n",
"103795\n",
"107302\n",
"108296\n",
"108297\n",
"109211\n",
"109305\n",
"109773\n",
"110561\n",
"110873\n",
"113368\n",
"116927\n",
"118062\n",
"118250\n",
"119143\n",
"120435\n",
"124177\n",
"125538\n",
"128322\n",
"129429\n",
"130498\n"
]
}
],
"execution_count": 75
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-07-31T19:35:10.949715Z",
"start_time": "2024-07-31T19:35:09.846007Z"
}
},
"cell_type": "code",
"source": "",
"id": "2bb88967eb45bcec",
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"IOPub data rate exceeded.\n",
"The Jupyter server will temporarily stop sending output\n",
"to the client in order to avoid crashing it.\n",
"To change this limit, set the config variable\n",
"`--ServerApp.iopub_data_rate_limit`.\n",
"\n",
"Current values:\n",
"ServerApp.iopub_data_rate_limit=1000000.0 (bytes/sec)\n",
"ServerApp.rate_limit_window=3.0 (secs)\n",
"\n"
]
}
],
"execution_count": 52
},
{
"metadata": {},
"cell_type": "code",
"outputs": [],
"execution_count": null,
"source": "",
"id": "f7c0742941b4f2d1"
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}