diff --git a/imports/energy_systems/water_to_water_hp_parameters.py b/imports/energy_systems/water_to_water_hp_parameters.py index e69de29b..4d712742 100644 --- a/imports/energy_systems/water_to_water_hp_parameters.py +++ b/imports/energy_systems/water_to_water_hp_parameters.py @@ -0,0 +1,173 @@ +""" +WaterToWaterHPParameters import the heat pump information +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2021 Project Author Peter Yefi peteryefi@gmail.com +""" + +import pandas as pd +from typing import Dict +from city_model_structure.energy_systems.water_to_water_hp import WaterToWaterHP +from city_model_structure.energy_system import EnergySystem +from scipy.optimize import curve_fit +import numpy as np +from typing import List + + +class WaterToWaterHPParameters: + """ + WaterToWaterHPParameters class + """ + + def __init__(self, city, base_path): + self._city = city + self._base_path = (base_path / 'heat_pumps/water_to_water.xlsx') + + def _read_file(self) -> Dict: + """ + reads xlsx file containing water to water heat pump information + into a dictionary + :return : Dict + """ + xl_file = pd.ExcelFile(self._base_path) + heat_pump_dfs = {sheet_name: xl_file.parse(sheet_name) + for sheet_name in xl_file.sheet_names} + + hp_data = {} + flow_rates = { + '156': [2.84, 4.23, 5.68], + '256': [4.73, 7.13, 9.446], + '335': [6.62, 9.97, 12.93], + } + + for sheet, dataframe in heat_pump_dfs.items(): + + df = heat_pump_dfs[sheet].dropna(axis=1, how='all') + df = df.iloc[3:, 6:35] + + if '156' in sheet: + hp_data[sheet] = self._extract_required_hp_data(df, [0, 10, 25, 40, 55, 67], flow_rates['156']) + elif '256' in sheet: + hp_data[sheet] = self._extract_required_hp_data(df, [0, 9, 24, 39, 54, 66], flow_rates['256']) + elif '335' in sheet: + hp_data[sheet] = self._extract_required_hp_data(df, [0, 11, 26, 41, 56, 69], flow_rates['335']) + + return hp_data + + def _extract_required_hp_data(self, dataframe, ranges, flow_rates): + """ + Extracts 156 Kw water to water heat pump data + :param dataframe: dataframe containing all data + :param ranges: the range of values to extract + :param flow_rates: the flow rates of water through pump + :return: Dict + """ + # extract data rows and columns + data = {'tc': self._extract_hp_data(dataframe, [1, 11, 21], ranges), + 'pd': self._extract_hp_data(dataframe, [2, 12, 22], ranges), + 'lwt': self._extract_hp_data(dataframe, [5, 15, 25], ranges), + 'fr': (self._extract_flow_and_ewt(dataframe, ranges, [1, 11, 21], flow_rates))[0], + 'ewt': (self._extract_flow_and_ewt(dataframe, ranges, [1, 11, 21], flow_rates))[1]} + # range values for extracting data + return data + + def _extract_hp_data(self, df, columns, ranges): + """ + Extract variable specific (LWT, PD or TC) data from water to water hp + :param df: the dataframe + :param columns: the columns to extract data from + :param ranges: the range of values to extract + :return: List + """ + data = df.iloc[ranges[0]:ranges[1], columns[0]].append(df.iloc[ranges[0]:ranges[1], columns[1]])\ + .append(df.iloc[ranges[0]:ranges[1], columns[2]]) + for i in range(1, 5): + data = data.append(df.iloc[ranges[i]:ranges[i + 1], columns[0]]).append( + df.iloc[ranges[i]:ranges[i + 1], columns[1]]).append(df.iloc[ranges[i]:ranges[i + 1], columns[2]]) + return data.dropna().values.tolist() + + def _extract_flow_and_ewt(self, df, ranges, columns, flow_rates): + """ + Create the flow and ewt data based on the length of the various + columns for the variables being extracted + :param df: the dataframe + :param ranges: the range of values to extract + :param columns: the columns to extract data from + :param flow_rates: flow rate values + :return: + """ + ewt_values = [-1.111111111, 4.444444444, 10, 15.55555556, 21.11111111] + length = [len(df.iloc[ranges[0]:ranges[1], columns[0]].dropna()), + len(df.iloc[ranges[0]:ranges[1], columns[1]].dropna()), + len(df.iloc[ranges[0]:ranges[1], columns[2]].dropna())] + + ewt_data = np.repeat(ewt_values[0], sum(length)) + flow_rates_data = np.repeat(flow_rates, length) + + for i in range(1, 5): + length = [len(df.iloc[ranges[i]:ranges[i + 1], columns[0]].dropna()), + len(df.iloc[ranges[i]:ranges[i + 1], columns[1]].dropna()), + len(df.iloc[ranges[i]:ranges[i + 1], columns[2]].dropna())] + flow_rates_data = np.append(flow_rates_data, np.repeat(flow_rates, length)) + ewt_data = np.append(ewt_data, np.repeat(ewt_values[i], sum(length))) + + return flow_rates_data.tolist(), ewt_data.tolist() + + def enrich_city(self): + """ + Enriches the city with information from file + """ + heap_pump_data = self._read_file() + for model, data in heap_pump_data.items(): + heat_pump = WaterToWaterHP() + heat_pump.model = model.strip() + heat_pump.total_cooling_capacity = data['tc'] + heat_pump.power_demand = data['pd'] + heat_pump.flow_rate = data['fr'] + heat_pump.entering_water_temp = data['ewt'] + heat_pump.leaving_water_temp = data['lwt'] + heat_pump.power_demand_coff = self._compute_coefficients(data, data_type='power') + heat_pump.total_cooling_capacity_coff = self._compute_coefficients(data) + + energy_system = EnergySystem(heat_pump.model, 0, [], None) + energy_system.water_to_water_hp = heat_pump + self._city.add_city_object(energy_system) + return self._city + + def _compute_coefficients(self, heat_pump_data: Dict, data_type="heat_output") -> List[float]: + """ + Compute heat output and electrical demand coefficients + from heating performance data + :param heat_pump_data: a dictionary of heat pump data. + :param data_type: string to indicate whether coefficient are power demands + or heat output coefficients. Default is heat output + :return: Tuple[Dict, Dict] + """ + demand = heat_pump_data['tc'] if data_type == "heat_output" else heat_pump_data['pd'] + + # Compute heat output coefficients + popt, _ = curve_fit(self._objective_function, [heat_pump_data['ewt'], heat_pump_data['lwt'], heat_pump_data['fr']], + demand) + return popt.tolist() + + def _objective_function(self, xdata: List, a1: float, a2: float, a3: float, a4: float, a5: float, a6: float, + a7: float, a8: float, a9: float, a10: float, a11: float) -> float: + """ + 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 + :param a7: float + :param a8: float + :param a9: float + :param a10: float + :param a11: float + :return: + """ + x, y, t = xdata + return (a1 * x ** 2) + (a2 * x) + (a3 * y ** 2) + (a4 * y) + (a5 * t ** 2) + (a6 * t) + (a7 * x * y) + ( + a8 * x * t) + (a9 * y * t) + (a10 * x * y * t) + a11 +