From aa7463cb9d213188336957086c7acb0fcec1fba7 Mon Sep 17 00:00:00 2001 From: Peter Yefi Date: Wed, 26 Jan 2022 10:42:01 -0500 Subject: [PATCH] Added separate classes of water to water and air source hp. Refactored energy systems factory --- .../energy_systems/air_source_hp_export.py | 51 ++++++++++++ exports/energy_systems/heat_pump_export.py | 82 +++++++++---------- .../water_to_water_hp_export.py | 56 +++++++++++++ exports/energy_systems_factory.py | 16 ++-- 4 files changed, 159 insertions(+), 46 deletions(-) create mode 100644 exports/energy_systems/air_source_hp_export.py create mode 100644 exports/energy_systems/water_to_water_hp_export.py diff --git a/exports/energy_systems/air_source_hp_export.py b/exports/energy_systems/air_source_hp_export.py new file mode 100644 index 00000000..4ab8ad1a --- /dev/null +++ b/exports/energy_systems/air_source_hp_export.py @@ -0,0 +1,51 @@ +""" +AirSourceHPExport exports air source values after executing insel. +Multiple files are generated for the export +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2021 Project Author Peter Yefi peteryefi@gmail.com +""" +from exports.energy_systems.heat_pump_export import HeatPumpExport +from typing import List, Tuple, Union + + +class AirSourceHPExport(HeatPumpExport): + """ + Exports heat pump values as multiple files + after executing insel + """ + + def __init__(self, base_path, city, output_path): + template_path = (base_path / 'heat_pumps/air_source_tmpl.txt') + super().__init__(base_path, city, output_path, template_path) + + def _extract_model_coff(self, hp_model: str, data_type='heat') -> Union[Tuple[List, List], None]: + """ + Extracts heat pump coefficient data for a specific + model. e.g 012, 140 + :param hp_model: the model type + :param data_type: indicates whether we're extracting cooling + or heating perfarmcn coefficients + :return: + """ + for energy_system in self._city.energy_systems: + if energy_system.air_source_hp.model == hp_model: + if data_type == 'heat': + return energy_system.air_source_hp.heating_capacity_coff, energy_system.air_source_hp.heating_comp_power_coff + return energy_system.air_source_hp.cooling_capacity_coff, energy_system.air_source_hp.cooling_comp_power_coff + return None + + def execute_insel(self, user_input, hp_model, data_type): + """ + Runs insel and produces output files + Runs insel and write the necessary files + :param user_input: a dictionary containing the user + values necessary to run insel + :param hp_model: a string that indicates the heat + pump model to be used e.g. 012, 015 + :param data_type: a string that indicates whether + insel should run for heat or cooling performance + :return: + :return: + """ + capacity_coeff, power_coeff = self._extract_model_coff(hp_model, data_type) + super(AirSourceHPExport, self)._run_insel(user_input, capacity_coeff, power_coeff) diff --git a/exports/energy_systems/heat_pump_export.py b/exports/energy_systems/heat_pump_export.py index 754b578a..5037dd75 100644 --- a/exports/energy_systems/heat_pump_export.py +++ b/exports/energy_systems/heat_pump_export.py @@ -1,5 +1,5 @@ """ -HeatPumpExport exports heatpump coefficient into several formats +HeatPumpExport exports heatpump outputs into several files after insel execution SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2021 Project Author Peter Yefi peteryefi@gmail.com """ @@ -16,8 +16,9 @@ class HeatPumpExport: of some defined function """ - def __init__(self, base_path, city, output_path): - self._template_path = (base_path / 'heat_pumps/template.txt') + def __init__(self, base_path, city, output_path, template, water_temp=None): + self._template_path = template + self._water_temp = water_temp self._constants_path = (base_path / 'heat_pumps/constants.yaml') # needed to compute max demand. self._demand_path = (base_path / 'heat_pumps/demand.txt') @@ -26,21 +27,17 @@ class HeatPumpExport: self._base_path = base_path self._output_path = output_path - def run_insel(self, user_input: Dict, hp_model: str, data_type: str) -> None: + def _run_insel(self, user_input: Dict, capacity_coeff: List, power_coeff: List) -> None: """ Runs insel and write the necessary files :param user_input: a dictionary containing the user values necessary to run insel - :param hp_model: a string that indicates the heat - pump model to be used e.g. 012, 015 - :param data_type: a string that indicates whether - insel should run for heat or cooling performance + :param capacity_coeff: a list containing capacity coefficients + :param power_coeff: a list containing power demand coefficients :return: """ self._input_data = user_input - # update input data with other data necessary to run insel - capacity_coff, comp_power_coff = self._extract_model_coff(hp_model, data_type) - self._update_input_data_with_coff(capacity_coff, comp_power_coff) + self._update_input_data_with_coff(capacity_coeff, power_coeff) # update input data with constants self._update_input_data_with_constants() # update input data with input and output files for insel @@ -99,6 +96,7 @@ class HeatPumpExport: self._input_data['fileOut9']: ['Day', 'Daily Fuel Consumption of Auxiliary Heater (m3)'], self._input_data['fileOut10']: ['Year', 'Month', 'Day', 'Hour', 'HP Electricity Demand (kWh)'] } + for file_path, header in header_data.items(): file_path = file_path.strip("'") df = pd.read_csv(file_path, header=None, sep='\s+') @@ -122,6 +120,9 @@ class HeatPumpExport: self._input_data["fileOut8"] = f"'{str((self._base_path / 'heat_pumps/monthly_hp_electricity_demand.csv'))}'" self._input_data["fileOut9"] = f"'{str((self._base_path / 'heat_pumps/daily_fossil_fuel_consumption.csv'))}'" self._input_data["fileOut10"] = f"'{str((self._base_path / 'heat_pumps/hp_hourly_electricity_demand.csv'))}'" + # include water temperature for water to water heat pump + if self._water_temp is not None: + self._input_data['WaterTemperature'] = f"'{str(self._water_temp)}'" def _delete_existing_output_files(self): """ @@ -161,41 +162,40 @@ class HeatPumpExport: self._input_data["TESCapacity"] = self._input_data["HoursOfStorageAtMaxDemand"] * (max_demand * 3.6) / ( (self._input_data["Cp"] / 1000) * self._input_data["TemperatureDifference"]) - def _update_input_data_with_coff(self, capacity_coff: List, comp_power_coff: List): + def _update_input_data_with_coff(self, a_coeff: List, b_coeff: List): """ Updates the user data with coefficients derived from imports - :param capacity_coff: heat or cooling capacity coefficients - :param comp_power_coff: heat or cooling comppressor power coefficients + :param a_coeff: insel a coefficient values + :param b_coeff: insel b coefficient values + Meaning of a and b are in the respective models for air source heat pump + and water to water source heat pump :return: """ - self._input_data["a1"] = capacity_coff[0] - self._input_data["a2"] = capacity_coff[1] - self._input_data["a3"] = capacity_coff[2] - self._input_data["a4"] = capacity_coff[3] - self._input_data["a5"] = capacity_coff[4] - self._input_data["a6"] = capacity_coff[5] - self._input_data["b1"] = comp_power_coff[0] - self._input_data["b2"] = comp_power_coff[1] - self._input_data["b3"] = comp_power_coff[2] - self._input_data["b4"] = comp_power_coff[3] - self._input_data["b5"] = comp_power_coff[4] - self._input_data["b6"] = comp_power_coff[5] + self._input_data["a1"] = a_coeff[0] + self._input_data["a2"] = a_coeff[1] + self._input_data["a3"] = a_coeff[2] + self._input_data["a4"] = a_coeff[3] + self._input_data["a5"] = a_coeff[4] + self._input_data["a6"] = a_coeff[5] + self._input_data["b1"] = b_coeff[0] + self._input_data["b2"] = b_coeff[1] + self._input_data["b3"] = b_coeff[2] + self._input_data["b4"] = b_coeff[3] + self._input_data["b5"] = b_coeff[4] + self._input_data["b6"] = b_coeff[5] - def _extract_model_coff(self, hp_model: str, data_type='heat') -> Union[Tuple[List, List], None]: - """ - Extracts heat pump coefficient data for a specific - model. e.g 012, 140 - :param hp_model: the model type - :param data_type: indicates whether we're extracting cooling - or heating perfarmcn coefficients - :return: - """ - for energy_system in self._city.energy_systems: - if energy_system.heat_pump.model == hp_model: - if data_type == 'heat': - return energy_system.heat_pump.heating_capacity_coff, energy_system.heat_pump.heating_comp_power_coff - return energy_system.heat_pump.cooling_capacity_coff, energy_system.heat_pump.cooling_comp_power_coff - return None + # additional coefficients for water to water source + if self._water_temp is not None: + self._input_data["a7"] = a_coeff[6] + self._input_data["a8"] = a_coeff[7] + self._input_data["a9"] = a_coeff[8] + self._input_data["a10"] = a_coeff[9] + self._input_data["a11"] = a_coeff[10] + self._input_data["b7"] = b_coeff[6] + self._input_data["b8"] = b_coeff[7] + self._input_data["b9"] = b_coeff[8] + self._input_data["b10"] = b_coeff[9] + self._input_data["b11"] = b_coeff[10] def _get_user_out_put(self): """ diff --git a/exports/energy_systems/water_to_water_hp_export.py b/exports/energy_systems/water_to_water_hp_export.py new file mode 100644 index 00000000..b7d0fc7f --- /dev/null +++ b/exports/energy_systems/water_to_water_hp_export.py @@ -0,0 +1,56 @@ +""" +WaterToWaterHPExport exports water to water values after executing insel. +Multiple files are generated for the export +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2021 Project Author Peter Yefi peteryefi@gmail.com +""" +from exports.energy_systems.heat_pump_export import HeatPumpExport +from typing import List, Tuple, Union + +class WaterToWaterHPExport(HeatPumpExport): + """ + Exports heat pump values as multiple output files + after executing insel + """ + + def __init__(self, base_path, city, output_path): + template_path = (base_path / 'heat_pumps/water_to_water_tmpl.txt') + water_temp = (base_path / 'heat_pumps/wt_hourly3.txt') + super().__init__(base_path, city, output_path, template_path, water_temp) + + def _extract_model_coff(self, hp_model: str, data_type='heat') -> Union[Tuple[List, List], None]: + """ + Extracts heat pump coefficient data for a specific + model. e.g 012, 140 + :param hp_model: the model type + :param data_type: indicates whether we're extracting cooling + or heating perfarmcn coefficients + :return: + """ + for energy_system in self._city.energy_systems: + if energy_system.water_to_water_hp.model == hp_model: + return energy_system.water_to_water_hp.power_demand_coff, \ + energy_system.water_to_water_hp.heat_output_coff + return None + + def execute_insel(self, user_input, hp_model, data_type): + """ + Runs insel and produces output files + Runs insel and write the necessary files + :param user_input: a dictionary containing the user + values necessary to run insel + :param hp_model: a string that indicates the heat + pump model to be used e.g. 012, 015 + :param data_type: a string that indicates whether + insel should run for heat or cooling performance + :return: + :return: + """ + pow_demand_coeff, heat_output_coeff = self._extract_model_coff(hp_model, data_type) + super(WaterToWaterHPExport, self)._run_insel(user_input, pow_demand_coeff, heat_output_coeff) + + + + + + diff --git a/exports/energy_systems_factory.py b/exports/energy_systems_factory.py index 6cdf5a2e..1ebdfeca 100644 --- a/exports/energy_systems_factory.py +++ b/exports/energy_systems_factory.py @@ -6,6 +6,8 @@ Copyright © 2020 Project Author Peter Yefi peteryefi@gmail.com from pathlib import Path from exports.energy_systems.heat_pump_export import HeatPumpExport +from exports.energy_systems.air_source_hp_export import AirSourceHPExport +from exports.energy_systems.water_to_water_hp_export import WaterToWaterHPExport class EnergySystemsExportFactory: @@ -23,18 +25,22 @@ class EnergySystemsExportFactory: self._data_type = data_type self._output_path = output_path - def _export_heat_pump(self): + def _export_heat_pump(self, source): """ Exports heat pump performance data as coefficients of some objective function :return: None """ - HeatPumpExport(self._base_path, self._city, self._output_path)\ - .run_insel(self._user_input, self._hp_model, self._data_type) + if source == 'air': + AirSourceHPExport(self._base_path, self._city, self._output_path)\ + .execute_insel(self._user_input, self._hp_model, self._data_type) + elif source == 'water': + WaterToWaterHPExport(self._base_path, self._city, self._output_path)\ + .execute_insel(self._user_input, self._hp_model, self._data_type) - def export(self): + def export(self, source='air'): """ Export the city given to the class using the given export type handler :return: None """ - return getattr(self, '_export_heat_pump', lambda: None)() + return getattr(self, '_export_heat_pump', lambda: None)(source)