|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# -*- coding: utf-8 -*- |
| 3 | +""" |
| 4 | +Created on Mon May 19 11:27:46 2025 |
| 5 | +
|
| 6 | +@author: casper |
| 7 | +
|
| 8 | +This file extracts values from the results file to make the Sankey diagram. |
| 9 | + The diagram needs to be made manually in e!Sankey which only runs on Windows. |
| 10 | +""" |
| 11 | + |
| 12 | +import os |
| 13 | +import numpy as np |
| 14 | +import pandas as pd |
| 15 | + |
| 16 | +from GetVariables import * |
| 17 | +# python file under same folder |
| 18 | + |
| 19 | +#CWD = os.getcwd() |
| 20 | +CWD = os.path.dirname(os.path.abspath(__file__)) |
| 21 | +mat_file_name = os.path.join(CWD, "simulations", "2025-07-10_base-crit", "2025-07-10-base-DetailedPlantFiveHubs.mat") |
| 22 | + |
| 23 | +nBui = 5 # Ensure this is consistent with the mat file |
| 24 | +_i = r'%%i%%' # placeholder string to be replaced with index |
| 25 | +J_to_kWh = 2.7777777777777776e-07 |
| 26 | + |
| 27 | +#%% read results file |
| 28 | +var_list = list() |
| 29 | +# buildings |
| 30 | +var_list_pre_index = [ |
| 31 | + f'bui[{_i}].ets.PCoo', |
| 32 | + f'bui[{_i}].dHChiWat_flow', |
| 33 | + f'bui[{_i}].dHHeaWat_flow', |
| 34 | + f'bui[{_i}].bui.disFloHea.PPum', |
| 35 | + f'bui[{_i}].bui.disFloCoo.PPum', |
| 36 | + f'QEtsHex_flow.u[{_i}]'] |
| 37 | +var_list += index_var_list(var_list_pre_index, |
| 38 | + _i, |
| 39 | + range(1,nBui+1)) |
| 40 | +# bui[1] doesn't have dhw |
| 41 | +var_list += index_var_list([f'bui[{_i}].dHHotWat_flow', |
| 42 | + f'bui[{_i}].ets.tanDhw.PEle'], |
| 43 | + _i, |
| 44 | + range(2,nBui+1)) |
| 45 | +# ground connection has (nBui + 1) elements |
| 46 | +var_list += index_var_list(f'dis.heatPorts[{_i}].Q_flow', |
| 47 | + _i, |
| 48 | + range(1,nBui+2)) |
| 49 | +# variables without an index |
| 50 | +var_list += ['cenPla.gen.ind.ySea', |
| 51 | + 'cenPla.gen.hex.Q1_flow', |
| 52 | + 'cenPla.gen.heaPum.P', |
| 53 | + 'cenPla.gen.heaPum.QCon_flow', |
| 54 | + 'cenPla.gen.heaPum.QEva_flow', |
| 55 | + 'cenPla.QBorPer_flow', |
| 56 | + 'cenPla.QBorCen_flow', |
| 57 | + 'cenPla.gen.fanDryCoo.P', |
| 58 | + 'cenPla.gen.pumDryCoo.P', |
| 59 | + 'cenPla.gen.dryCoo.Q1_flow', |
| 60 | + 'pumDis.P', |
| 61 | + 'PEleNonHva.y', |
| 62 | + 'PFanBuiSum.y', |
| 63 | + 'EPvBat.u' |
| 64 | + ] |
| 65 | +results = get_vars(var_list, |
| 66 | + mat_file_name, |
| 67 | + 'dymola') |
| 68 | + |
| 69 | +#%% process results data |
| 70 | +# (source node, target node) |
| 71 | +# `energy carrier` influences colouring in the diagram |
| 72 | +data_dicts = [ |
| 73 | + { |
| 74 | + ("PV and bettery", "Electricity") : 0, |
| 75 | + ("Electricity", "Buildings fans + non HVAC") : 0, |
| 76 | + ("Electricity", "Pump coo") : 0, |
| 77 | + ("Electricity", "Pump hea") : 0, |
| 78 | + ("Electricity", "Pump DHW") : 0, |
| 79 | + ("Electricity", "ETS") : 0, |
| 80 | + ("Electricity", "Central plant chiller") : 0, |
| 81 | + ("Electricity", "Dry cooler") : 0, |
| 82 | + ("Electricity", "Pump district") : 0, |
| 83 | + ("Heat ambient", "Dry cooler") : 0, |
| 84 | + ("TEN", "Central plant chiller") : 0, |
| 85 | + ("Dry cooler", "Heat ambient") : 0, |
| 86 | + ("Central plant chiller", "TEN") : 0, |
| 87 | + ("Economiser", "TEN") : 0, |
| 88 | + ("Borefield", "TEN") : 0, |
| 89 | + ("Ground", "TEN") : 0, |
| 90 | + ("ETS", "Pump district") : 0, |
| 91 | + ("TEN", "Economiser") : 0, |
| 92 | + ("TEN", "Borefield") : 0, |
| 93 | + ("TEN", "Ground") : 0, |
| 94 | + ("Pump district", "ETS") : 0, |
| 95 | + ("Pump coo", "ETS") : 0, |
| 96 | + ("ETS", "Pump hea") : 0, |
| 97 | + ("ETS", "DHW") : 0 |
| 98 | + } |
| 99 | + for _ in range(5)] |
| 100 | + |
| 101 | +for sea in range(5): |
| 102 | +# for sea in range(1): |
| 103 | + if sea == 0: |
| 104 | + condition = None |
| 105 | + else: |
| 106 | + condition = np.array(results['cenPla.gen.ind.ySea'] == sea) |
| 107 | + |
| 108 | + data_dict = data_dicts[sea] |
| 109 | + |
| 110 | + # Electricity node |
| 111 | + data_dict[("PV and bettery", "Electricity")] = \ |
| 112 | + abs(integrate_with_condition(results, 'EPvBat.u', |
| 113 | + condition = condition)) |
| 114 | + data_dict[("Electricity", "Buildings fans + non HVAC")] = \ |
| 115 | + abs(integrate_with_condition(results, 'PEleNonHva.y', |
| 116 | + condition = condition)) + \ |
| 117 | + abs(integrate_with_condition(results, 'PFanBuiSum.y', |
| 118 | + condition = condition)) |
| 119 | + data_dict[("Electricity", "Central plant chiller")] = \ |
| 120 | + abs(integrate_with_condition(results, 'cenPla.gen.heaPum.P', |
| 121 | + condition = condition)) |
| 122 | + data_dict[("Electricity", "Dry cooler")] = \ |
| 123 | + abs(integrate_with_condition(results, 'cenPla.gen.fanDryCoo.P', |
| 124 | + condition = condition)) + \ |
| 125 | + abs(integrate_with_condition(results, 'cenPla.gen.pumDryCoo.P', |
| 126 | + condition = condition)) |
| 127 | + data_dict[("Electricity", "Pump district")] = \ |
| 128 | + abs(integrate_with_condition(results, 'pumDis.P', |
| 129 | + condition = condition)) |
| 130 | + # each building |
| 131 | + for i in range(1,nBui+1): |
| 132 | + data_dict[("Electricity", "ETS")] += \ |
| 133 | + abs(integrate_with_condition(results, f'bui[{i}].ets.PCoo', |
| 134 | + condition = condition)) |
| 135 | + data_dict[("Electricity", "Pump coo")] += \ |
| 136 | + abs(integrate_with_condition(results, f'bui[{i}].bui.disFloCoo.PPum', |
| 137 | + condition = condition)) |
| 138 | + data_dict[("Electricity", "Pump hea")] += \ |
| 139 | + abs(integrate_with_condition(results, f'bui[{i}].bui.disFloHea.PPum', |
| 140 | + condition = condition)) |
| 141 | + if i != 1: # bui[1] doesn't have dhw |
| 142 | + data_dict[("Electricity", "Pump DHW")] += \ |
| 143 | + abs(integrate_with_condition(results, f'bui[{i}].ets.tanDhw.PEle', |
| 144 | + condition = condition)) |
| 145 | + |
| 146 | + # Central plant node, previously computed links excluded |
| 147 | + data_dict[("Heat ambient", "Dry cooler")] = \ |
| 148 | + abs(integrate_with_condition(results, 'cenPla.gen.dryCoo.Q1_flow', |
| 149 | + sign = 'negative', |
| 150 | + condition = condition)) |
| 151 | + data_dict[("Dry cooler", "Heat ambient")] = \ |
| 152 | + abs(integrate_with_condition(results, 'cenPla.gen.dryCoo.Q1_flow', |
| 153 | + sign = 'positive', |
| 154 | + condition = condition)) |
| 155 | + data_dict[("Central plant chiller", "TEN")] = \ |
| 156 | + abs(integrate_with_condition(results, 'cenPla.gen.heaPum.QCon_flow', |
| 157 | + sign = 'positive', |
| 158 | + condition = condition)) |
| 159 | + data_dict[("TEN", "Central plant chiller")] = \ |
| 160 | + abs(integrate_with_condition(results, 'cenPla.gen.heaPum.QCon_flow', |
| 161 | + sign = 'negative', |
| 162 | + condition = condition)) |
| 163 | + |
| 164 | + # TEN node, previously computed links excluded |
| 165 | + data_dict[("Economiser", "TEN")] = \ |
| 166 | + abs(integrate_with_condition(results, 'cenPla.gen.hex.Q1_flow', |
| 167 | + sign = 'positive', |
| 168 | + condition = condition)) |
| 169 | + data_dict[("TEN", "Economiser")] = \ |
| 170 | + abs(integrate_with_condition(results, 'cenPla.gen.hex.Q1_flow', |
| 171 | + sign = 'negative', |
| 172 | + condition = condition)) |
| 173 | + data_dict[("Borefield", "TEN")] = \ |
| 174 | + abs(integrate_with_condition(results, 'cenPla.QBorCen_flow', |
| 175 | + sign = 'positive', |
| 176 | + condition = condition)) + \ |
| 177 | + abs(integrate_with_condition(results, 'cenPla.QBorPer_flow', |
| 178 | + sign = 'positive', |
| 179 | + condition = condition)) |
| 180 | + data_dict[("TEN", "Borefield")] = \ |
| 181 | + abs(integrate_with_condition(results, 'cenPla.QBorCen_flow', |
| 182 | + sign = 'negative', |
| 183 | + condition = condition)) + \ |
| 184 | + abs(integrate_with_condition(results, 'cenPla.QBorPer_flow', |
| 185 | + sign = 'negative', |
| 186 | + condition = condition)) |
| 187 | + # each pipe section |
| 188 | + for i in range(1,nBui+2): |
| 189 | + data_dict[("Ground", "TEN")] += \ |
| 190 | + abs(integrate_with_condition(results, f'dis.heatPorts[{i}].Q_flow', |
| 191 | + sign = 'positive', |
| 192 | + condition = condition)) |
| 193 | + data_dict[("TEN", "Ground")] += \ |
| 194 | + abs(integrate_with_condition(results, f'dis.heatPorts[{i}].Q_flow', |
| 195 | + sign = 'negative', |
| 196 | + condition = condition)) |
| 197 | + # each building |
| 198 | + for i in range(1,nBui+1): |
| 199 | + data_dict[("Pump district", "ETS")] += \ |
| 200 | + abs(integrate_with_condition(results, f'QEtsHex_flow.u[{i}]', |
| 201 | + sign = 'positive', |
| 202 | + condition = condition)) |
| 203 | + data_dict[("ETS", "Pump district")] += \ |
| 204 | + abs(integrate_with_condition(results, f'QEtsHex_flow.u[{i}]', |
| 205 | + sign = 'negative', |
| 206 | + condition = condition)) |
| 207 | + |
| 208 | + # ETS node, previously computed links excluded |
| 209 | + # each building |
| 210 | + for i in range(1,nBui+1): |
| 211 | + data_dict[("Pump coo", "ETS")] += \ |
| 212 | + abs(integrate_with_condition(results, f'bui[{i}].dHChiWat_flow', |
| 213 | + condition = condition)) |
| 214 | + data_dict[("ETS", "Pump hea")] += \ |
| 215 | + abs(integrate_with_condition(results, f'bui[{i}].dHHeaWat_flow', |
| 216 | + condition = condition)) |
| 217 | + if i != 1: # bui[1] doesn't have dhw |
| 218 | + data_dict[("ETS", "DHW")] += \ |
| 219 | + abs(integrate_with_condition(results, f'bui[{i}].dHHotWat_flow', |
| 220 | + condition = condition)) |
| 221 | + |
| 222 | +#%% output to Excel |
| 223 | +seasons = ['Whole year', 'Winter', 'Spring', 'Summer', 'Fall'] |
| 224 | +with pd.ExcelWriter('sankey_modelica.xlsx', engine='openpyxl') as writer: |
| 225 | + for season, data_dict in zip(seasons, data_dicts): |
| 226 | + # Convert the dictionary to a DataFrame |
| 227 | + df = pd.DataFrame(list(data_dict.items()), columns=['From-To', 'kWh']) |
| 228 | + df[['From', 'To']] = pd.DataFrame(df['From-To'].tolist(), index=df.index) |
| 229 | + df['kWh'] = df['kWh'] * J_to_kWh |
| 230 | + df = df[['From', 'To', 'kWh']] |
| 231 | + |
| 232 | + df.to_excel(writer, sheet_name=season, index=False) |
0 commit comments