2021-10-18 11:37:20 -04:00
|
|
|
"""
|
2021-12-15 04:19:10 -05:00
|
|
|
AirSourceHeatPumpParameters import the heat pump information
|
2021-10-18 11:37:20 -04:00
|
|
|
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
2022-04-08 09:35:33 -04:00
|
|
|
Copyright © 2022 Concordia CERC group
|
|
|
|
Project Coder Peter Yefi peteryefi@gmail.comCode contributor Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
|
2021-10-18 11:37:20 -04:00
|
|
|
"""
|
|
|
|
|
2021-10-20 09:00:59 -04:00
|
|
|
import pandas as pd
|
|
|
|
from typing import Dict
|
2021-12-15 04:19:10 -05:00
|
|
|
from city_model_structure.energy_systems.air_source_hp import AirSourceHP
|
2021-10-21 09:50:02 -04:00
|
|
|
from city_model_structure.energy_system import EnergySystem
|
2021-11-01 10:53:51 -04:00
|
|
|
from scipy.optimize import curve_fit
|
|
|
|
import numpy as np
|
|
|
|
from typing import List
|
|
|
|
import itertools
|
2021-10-20 09:00:59 -04:00
|
|
|
|
2021-10-18 11:37:20 -04:00
|
|
|
|
2021-12-15 04:19:10 -05:00
|
|
|
class AirSourceHeatPumpParameters:
|
2021-10-26 07:11:48 -04:00
|
|
|
"""
|
2021-12-15 04:19:10 -05:00
|
|
|
AirSourceHeatPumpParameters class
|
2021-10-18 11:37:20 -04:00
|
|
|
"""
|
|
|
|
|
2021-10-26 07:11:48 -04:00
|
|
|
def __init__(self, city, base_path):
|
|
|
|
self._city = city
|
2022-04-08 13:38:32 -04:00
|
|
|
self._base_path = (base_path / 'heat_pumps/air_source.xlsx')
|
2021-10-20 09:00:59 -04:00
|
|
|
|
2021-10-26 07:11:48 -04:00
|
|
|
def _read_file(self) -> Dict:
|
|
|
|
"""
|
2021-10-18 11:37:20 -04:00
|
|
|
reads xlsx file containing the heat pump information
|
2021-10-20 09:00:59 -04:00
|
|
|
into a dictionary
|
|
|
|
:return : Dict
|
2021-10-18 11:37:20 -04:00
|
|
|
"""
|
2021-10-26 07:11:48 -04:00
|
|
|
xl_file = pd.ExcelFile(self._base_path)
|
2021-12-15 04:19:10 -05:00
|
|
|
|
2021-10-26 07:11:48 -04:00
|
|
|
heat_pump_dfs = {sheet_name: xl_file.parse(sheet_name)
|
|
|
|
for sheet_name in xl_file.sheet_names}
|
2021-10-18 11:37:20 -04:00
|
|
|
|
2021-10-26 07:11:48 -04:00
|
|
|
cooling_data = {}
|
|
|
|
heating_data = {}
|
2021-10-20 09:00:59 -04:00
|
|
|
|
2021-10-26 07:11:48 -04:00
|
|
|
for sheet, dataframe in heat_pump_dfs.items():
|
2021-12-15 04:19:10 -05:00
|
|
|
|
|
|
|
if 'Summary' in sheet:
|
|
|
|
continue
|
|
|
|
|
2021-10-26 07:11:48 -04:00
|
|
|
# Remove nan rows and columns and extract cooling and heating data
|
|
|
|
# for each sheet
|
|
|
|
df = heat_pump_dfs[sheet].dropna(axis=1, how='all')
|
|
|
|
cooling_df = df.iloc[4:34, 0:8]
|
|
|
|
heating_df = df.iloc[4:29, 8:20]
|
2021-10-20 09:00:59 -04:00
|
|
|
|
2021-10-26 07:11:48 -04:00
|
|
|
# extract the data into dictionaries each sheet is a key entry in the
|
|
|
|
# dictionary
|
|
|
|
cooling_data[sheet] = {}
|
|
|
|
heating_data[sheet] = {}
|
|
|
|
i = 0
|
|
|
|
# for each sheet extract data for twout/Ta.RU temperatures. Thus, the twout
|
|
|
|
# temp is the key for the values of pf,pa,qw data
|
|
|
|
while i < 25:
|
|
|
|
cooling_data[sheet][cooling_df.iloc[i][0]] = cooling_df.iloc[i + 1:i + 4, 2:8].values.tolist()
|
|
|
|
heating_data[sheet][heating_df.iloc[i][0]] = heating_df.iloc[i + 1:i + 4, 2:8].values.tolist()
|
|
|
|
i = i + 5
|
|
|
|
# extract the last cooling data
|
2021-10-29 11:26:48 -04:00
|
|
|
cooling_data[sheet][cooling_df.iloc[i][0]] = cooling_df.iloc[i + 1:i + 4, 2:8].values.tolist()
|
2021-10-26 07:11:48 -04:00
|
|
|
return {"cooling": cooling_data, "heating": heating_data}
|
2021-10-20 09:00:59 -04:00
|
|
|
|
2021-10-26 07:11:48 -04:00
|
|
|
def enrich_city(self):
|
|
|
|
"""
|
2021-10-18 11:37:20 -04:00
|
|
|
Enriches the city with information from file
|
|
|
|
"""
|
2021-12-15 04:19:10 -05:00
|
|
|
heat_pump_data = self._read_file()
|
2021-10-26 07:11:48 -04:00
|
|
|
for (k_cool, v_cool), (k_heat, v_heat) in \
|
2021-12-15 04:19:10 -05:00
|
|
|
zip(heat_pump_data["cooling"].items(), heat_pump_data["heating"].items()):
|
|
|
|
heat_pump = AirSourceHP()
|
2021-10-26 07:11:48 -04:00
|
|
|
heat_pump.model = k_cool
|
|
|
|
h_data = self._extract_heat_pump_data(v_heat)
|
|
|
|
c_data = self._extract_heat_pump_data(v_cool)
|
|
|
|
heat_pump.cooling_capacity = c_data[0]
|
|
|
|
heat_pump.cooling_comp_power = c_data[1]
|
2022-03-10 12:44:04 -05:00
|
|
|
heat_pump.cooling_capacity_coff = self._compute_coefficients(c_data, "cool")
|
2021-10-26 07:11:48 -04:00
|
|
|
heat_pump.heating_capacity = h_data[0]
|
|
|
|
heat_pump.heating_comp_power = h_data[1]
|
2022-03-10 12:44:04 -05:00
|
|
|
heat_pump.heating_capacity_coff = self._compute_coefficients(h_data)
|
2021-11-01 10:53:51 -04:00
|
|
|
|
2021-10-26 07:11:48 -04:00
|
|
|
energy_system = EnergySystem('{} capacity heat pump'.format(heat_pump.model), 0, [], None)
|
2021-12-15 04:19:10 -05:00
|
|
|
energy_system.air_source_hp = heat_pump
|
2021-10-26 07:11:48 -04:00
|
|
|
self._city.add_city_object(energy_system)
|
|
|
|
return self._city
|
2021-10-21 09:50:02 -04:00
|
|
|
|
2021-11-10 05:17:01 -05:00
|
|
|
def _extract_heat_pump_data(self, heat_pump_capacity_data: Dict) -> [List, List]:
|
2021-10-26 07:11:48 -04:00
|
|
|
"""
|
|
|
|
Fetches a list of metric based data for heat pump for various temperature,
|
|
|
|
eg. cooling capacity data for 12 capacity heat pump
|
|
|
|
for 6,7,8,9,10 and 11 degree celsius
|
|
|
|
:param heat_pump_capacity_data: the heat pump capacity data from the
|
|
|
|
which the metric specific data is fetched: {List}
|
|
|
|
:return: List
|
|
|
|
"""
|
|
|
|
cooling_heating_capacity_data = []
|
|
|
|
compressor_power_data = []
|
|
|
|
for _, metric_data in heat_pump_capacity_data.items():
|
|
|
|
cooling_heating_capacity_data.append(metric_data[0])
|
|
|
|
compressor_power_data.append(metric_data[1])
|
2021-11-01 10:53:51 -04:00
|
|
|
return [cooling_heating_capacity_data, compressor_power_data]
|
|
|
|
|
2021-11-10 05:17:01 -05:00
|
|
|
def _compute_coefficients(self, heat_pump_data: List, data_type="heat") -> List[float]:
|
2021-11-01 10:53:51 -04:00
|
|
|
"""
|
|
|
|
Compute heat output and electrical demand coefficients
|
|
|
|
from heating and cooling performance data
|
|
|
|
:param heat_pump_data: a list of heat pump data. eg. cooling capacity
|
|
|
|
:param data_type: string to indicate if data is cooling performance data
|
|
|
|
or heating performance data
|
|
|
|
:return: Tuple[Dict, Dict]
|
|
|
|
"""
|
2021-11-10 05:17:01 -05:00
|
|
|
# Determine the recurrence of temperature values. 6 repetitions for
|
|
|
|
# cooling performance and 5 repetition for heating performance
|
|
|
|
temp_multiplier = 5 if data_type == "heat" else 6
|
|
|
|
out_temp = [25, 30, 32, 35, 40, 45] * temp_multiplier
|
|
|
|
|
2021-11-01 10:53:51 -04:00
|
|
|
heat_x_values = np.repeat([-5, 0, 7, 10, 15], 6)
|
|
|
|
cool_x_values = np.repeat([6, 7, 8, 9, 10, 11], 6)
|
|
|
|
x_values = heat_x_values if data_type == "heat" else cool_x_values
|
2021-11-10 05:17:01 -05:00
|
|
|
x_values = x_values.tolist()
|
2021-11-01 10:53:51 -04:00
|
|
|
# convert list of lists to one list
|
2022-03-10 12:44:04 -05:00
|
|
|
|
|
|
|
hp_data = [i/j for i, j in
|
|
|
|
zip(list(itertools.chain.from_iterable(heat_pump_data[0])),
|
|
|
|
list(itertools.chain.from_iterable(heat_pump_data[1])))]
|
2021-11-01 10:53:51 -04:00
|
|
|
|
|
|
|
# Compute heat output coefficients
|
2022-03-10 12:44:04 -05:00
|
|
|
popt, _ = curve_fit(self._objective_function, [x_values, out_temp], hp_data)
|
2021-11-01 10:53:51 -04:00
|
|
|
return popt.tolist()
|
|
|
|
|
2021-11-10 05:17:01 -05:00
|
|
|
def _objective_function(self, xdata: List, a1: float, a2: float, a3: float, a4: float, a5: float, a6: float) -> float:
|
2021-11-01 10:53:51 -04:00
|
|
|
"""
|
|
|
|
Objective function for computing coefficients
|
|
|
|
:param xdata:
|
|
|
|
:param a1: float
|
|
|
|
:param a2: float
|
|
|
|
:param a3: float
|
|
|
|
:param a4: float
|
|
|
|
:param a5: float
|
|
|
|
:param a6: float
|
|
|
|
:return:
|
|
|
|
"""
|
|
|
|
x, y = xdata
|
|
|
|
return (a1 * x ** 2) + (a2 * x) + (a3 * x * y) + (a4 * y) + (a5 * y ** 2) + a6
|