hub/exports/energy_systems/heat_pump_export.py
2021-11-08 16:33:24 +00:00

147 lines
6.2 KiB
Python

"""
HeatPumpExport exports heatpump coefficient into several formats
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2021 Project Author Peter Yefi peteryefi@gmail.com
"""
import subprocess
from typing import List, Tuple, Union
import yaml
from string import Template
class HeatPumpExport:
"""
Exports heat pump values as coefficients
of some defined function
"""
def __init__(self, base_path, city):
self._template_path = (base_path / 'heat_pumps/template.txt')
self._constants_path = (base_path / 'heat_pumps/constants.yaml')
# needed to compute max demand.
self._demand_path = (base_path / 'heat_pumps/demand.txt')
self._city = city
self._input_data = None
self._base_path = base_path
def run_insel(self, user_input, hp_model, data_type) -> 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
: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)
# update input data with constants
self._update_input_data_with_constants()
# update input data with input and output files for insel
self._update_input_data_with_files()
insel_file_handler = None
insel_template_handler = None
try:
# run insel
insel_template_handler = open(self._template_path, "r")
insel_template_handler = insel_template_handler.read()
insel_template = Template(insel_template_handler).substitute(self._input_data)
# create the insel file and write the template with substituted values into it
insel_file = (self._base_path / 'heat_pumps/dompark_heat_pump.insel')
insel_file_handler = open(insel_file, "w")
insel_file_handler.write(insel_template)
# Now run insel
subprocess.call('insel', insel_file)
except IOError as err:
print("I/O exception: {}".format(err))
except subprocess.CalledProcessError as err:
print("Insel command error {}".format(err))
else:
print("Insel executed successfully")
finally:
insel_file_handler.close()
insel_template_handler.close()
def _update_input_data_with_files(self):
"""
Updates input data for insel with some files that will
be written to after insel runs. Also specifies and input file
which is the Heating Demand (demand.txt) file
:return:
"""
self._input_data["HeatingDemand"] = self._demand_path
self._input_data["fileOut1"] = (self._base_path / 'heat_pumps/technical_performance.csv')
self._input_data["fileOut2"] = (self._base_path / 'heat_pumps/system_daily_emissions.cs')
self._input_data["fileOut3"] = (self._base_path / 'heat_pumps/monthly_operational_costs.csv')
self._input_data["fileOut4"] = (self._base_path / 'heat_pumps/monthly_fossil_fuel_consumptions.csv')
self._input_data["fileOut5"] = (self._base_path / 'heat_pumps/system_monthly_emissions.csv')
self._input_data["fileOut6"] = (self._base_path / 'heat_pumps/daily_hp_electricity_demand.csv')
self._input_data["fileOut7"] = (self._base_path / 'heat_pumps/daily_operational_costs.csv')
self._input_data["fileOut8"] = (self._base_path / 'heat_pumps/monthly_hp_electricity_demand.csv')
self._input_data["fileOut9"] = (self._base_path / 'heat_pumps/daily_fossil_fuel_consumption.csv')
self._input_data["fileOut10"] = (self._base_path / 'heat_pumps/hp_hourly_electricity_demand.csv')
def _compute_max_demand(self):
"""
Retrieves the maximum demand value from
the demands text file
:return: float
"""
max_demand = -1
with open(self._demand_path) as file_handler:
for demand in file_handler.readlines():
if float(demand) > max_demand:
max_demand = float(demand)
return max_demand
def _update_input_data_with_constants(self):
with open(self._constants_path) as file:
constants_dict = yaml.load(file, Loader=yaml.FullLoader)
for key, value in constants_dict.items():
self._input_data[key] = value
# compute maximum demand. TODO: This should come from catalog in the future
max_demand = self._compute_max_demand()
# compute TESCapacity
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, comp_power_coff):
"""
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
: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]
def _extract_model_coff(self, hp_model, 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