Merge branch 'hp_energy_demand' into db_persistence

This commit is contained in:
Peter Yefi 2022-11-22 17:49:09 -05:00
commit 7974317d13
9 changed files with 1603 additions and 1949 deletions

View File

@ -13,13 +13,12 @@ Cp: 4190
Rhow: 1000 Rhow: 1000
TESDiameter: 5 TESDiameter: 5
AuxHeaterEfficiency: 0.9 AuxHeaterEfficiency: 0.9
HPNominalCapacity: 256
# These come from the data model according to other student's work # These come from the data model according to other student's work
ElecGridEF: 0.5 ElecGridEF: 0.5
ElectricityPrice: 0.073 ElectricityPrice: 0.073
# Water to Water HP constants # Water to Water HP constants
HPNominalCapacity: 256
LowestPossibleLoadFlow: 4.73 LowestPossibleLoadFlow: 4.73
HighestPossibleLoadFlow: 9.46 HighestPossibleLoadFlow: 9.46

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ Copyright © 2022 Concordia CERC group
Project Coder Peter Yefi peteryefi@gmail.com Project Coder Peter Yefi peteryefi@gmail.com
""" """
from exports.energy_systems.heat_pump_export import HeatPumpExport from exports.energy_systems.heat_pump_export import HeatPumpExport
from typing import List, Tuple, Union from typing import List, Dict, Union
class AirSourceHPExport(HeatPumpExport): class AirSourceHPExport(HeatPumpExport):
@ -15,17 +15,18 @@ class AirSourceHPExport(HeatPumpExport):
after executing insel after executing insel
""" """
def __init__(self, base_path, city, output_path, sim_type): def __init__(self, base_path, city, output_path, sim_type, demand_path=None):
""" """
:param base_path: path to energy system files :param base_path: path to energy system files
:param city: the city object :param city: the city object
:param output_path: the file to hold insel simulation results :param output_path: the file to hold insel simulation results
:param sim_type: the simulation type to run: 0 for series, 1 for parallel :param sim_type: the simulation type to run: 0 for series, 1 for parallel
:param demand_path: path to hourly energy demand file
""" """
tmp_file = 'heat_pumps/as_series.txt' if sim_type == 0 else 'heat_pumps/as_parallel.txt' tmp_file = 'heat_pumps/as_series.txt' if sim_type == 0 else 'heat_pumps/as_parallel.txt'
template_path = (base_path / tmp_file) template_path = (base_path / tmp_file)
super().__init__(base_path, city, output_path, template_path) super().__init__(base_path, city, output_path, template_path, demand_path)
def _extract_model_coff(self, hp_model: str, data_type='heat') -> Union[List, None]: def _extract_model_coff(self, hp_model: str, data_type='heat') -> Union[List, None]:
""" """
@ -43,7 +44,7 @@ class AirSourceHPExport(HeatPumpExport):
return energy_system.air_source_hp.cooling_capacity_coff return energy_system.air_source_hp.cooling_capacity_coff
return None return None
def execute_insel(self, user_input, hp_model, data_type): def execute_insel(self, user_input, hp_model, data_type) -> Union[Dict, None]:
""" """
Runs insel and produces output files Runs insel and produces output files
Runs insel and write the necessary files Runs insel and write the necessary files
@ -54,7 +55,6 @@ class AirSourceHPExport(HeatPumpExport):
:param data_type: a string that indicates whether :param data_type: a string that indicates whether
insel should run for heat or cooling performance insel should run for heat or cooling performance
:return: :return:
:return:
""" """
capacity_coeff = self._extract_model_coff(hp_model, data_type) capacity_coeff = self._extract_model_coff(hp_model, data_type)
super(AirSourceHPExport, self)._run_insel(user_input, capacity_coeff, 'air_source.insel') return super(AirSourceHPExport, self)._run_insel(user_input, capacity_coeff, 'air_source.insel')

View File

@ -5,7 +5,7 @@ Copyright © 2022 Concordia CERC group
Project Coder Peter Yefi peteryefi@gmail.com Project Coder Peter Yefi peteryefi@gmail.com
""" """
import os import os
from typing import List, Tuple, Union, Dict from typing import List, Union, Dict
import yaml import yaml
from string import Template from string import Template
import pandas as pd import pandas as pd
@ -17,18 +17,18 @@ class HeatPumpExport:
of some defined function of some defined function
""" """
def __init__(self, base_path, city, output_path, template, water_temp=None): def __init__(self, base_path, city, output_path, template, demand_path=None, water_temp=None):
self._template_path = template self._template_path = template
self._water_temp = water_temp self._water_temp = water_temp
self._constants_path = (base_path / 'heat_pumps/constants.yaml') self._constants_path = (base_path / 'heat_pumps/constants.yaml')
# needed to compute max demand. # needed to compute max demand.
self._demand_path = (base_path / 'heat_pumps/demand.txt') self._demand_path = (base_path / 'heat_pumps/demand.txt') if demand_path is None else demand_path
self._city = city self._city = city
self._input_data = None self._input_data = None
self._base_path = base_path self._base_path = base_path
self._output_path = output_path self._output_path = output_path
def _run_insel(self, user_input: Dict, capacity_coeff: List, filename: str) -> None: def _run_insel(self, user_input: Dict, capacity_coeff: List, filename: str) -> Union[Dict, None]:
""" """
Runs insel and write the necessary files Runs insel and write the necessary files
:param user_input: a dictionary containing the user :param user_input: a dictionary containing the user
@ -60,7 +60,7 @@ class HeatPumpExport:
# Writer headers to csv output files generated by insel # Writer headers to csv output files generated by insel
self._write_insel_output_headers() self._write_insel_output_headers()
# User output # User output
self._get_user_out_put() return self._get_user_out_put()
except IOError as err: except IOError as err:
print("I/O exception: {}".format(err)) print("I/O exception: {}".format(err))
finally: finally:
@ -72,8 +72,22 @@ class HeatPumpExport:
Write headers to the various csv file generated by insel Write headers to the various csv file generated by insel
:return: :return:
""" """
header_data = { header = [
self._input_data['fileOut1']: ['Year', ' Month', ' Day', 'Hour', 'Minute', 'HP Heat Output (kW)', 'Year', ' Month', ' Day', 'Hour', 'Minute', 'HP Heat Output (kW)', 'Heating Demand (kW)', 'HP output flow rate',
'Building Required Flow Rate', 'TES Charging Rate (kg/s)', 'Water Flow Rate After Splitter',
'water temperature after splitter', 'TES Discharging Rate (kg/s)', 'TES discharge temperature',
'Mixer Outlet Flow Rate (kg/s)', 'Mixer outlet temperature', 'Auxiliary heater fuel flow rate',
'Auxiliary heater energy input (kW)', 'Building Inlet Flow Rate (kg/s)', 'Building inlet temperature',
'Building return temperature', 'TES Return Flow Rate (kg/s)', 'TES return temperature',
'TES Bypass Line Flow Rate (kg/s)', 'TES bypass line temperature', 'Flow Rate from TES to mixer 2 (kg/s)',
'Temperature from Tes to mixer', 'HP Inlet Flow Rate (kg/s)', 'HP Inlet temperature', 'TES Node 1 Temperature',
'TES Node 2 Temperature', 'TES Node 3 Temperature', 'TES Node 4 Temperature', 'TES Energy Content (J)',
'HP Electricity Consumption (kW)', 'HP COP', 'Ambient Temperature', 'HP Operational Cost (CAD)',
'Auxiliary Heater Operational Cost (CAD)', 'Operational CO2 Emissions of HP (g)',
'Operational CO2 Emissions of Auxiliary Heater (g)']
if 'series' in str(self._template_path):
header = [
'Year', ' Month', ' Day', 'Hour', 'Minute', 'HP Heat Output (kW)',
'HP Electricity Consumption (kW)', 'HP COP', 'TES Charging Rate (kg/s)', 'HP Electricity Consumption (kW)', 'HP COP', 'TES Charging Rate (kg/s)',
'TES Discharging Rate (kg/s)', 'TES Node 1 Temperature', 'TES Node 2 Temperature', 'TES Discharging Rate (kg/s)', 'TES Node 1 Temperature', 'TES Node 2 Temperature',
'TES Node 3 Temperature', 'TES Node 4 Temperature', 'TES Energy Content (J)', 'TES Node 3 Temperature', 'TES Node 4 Temperature', 'TES Energy Content (J)',
@ -82,7 +96,9 @@ class HeatPumpExport:
'HP Operational Cost (CAD)', 'Auxiliary Heater Operational Cost (CAD)', 'HP Operational Cost (CAD)', 'Auxiliary Heater Operational Cost (CAD)',
'Operational CO2 Emissions of HP (g)', 'Operational CO2 Emissions of HP (g)',
'Operational CO2 Emissions of Auxiliary Heater (g)', 'Operational CO2 Emissions of Auxiliary Heater (g)',
'Return Temperature', 'Demand (kW)'], 'Return Temperature', 'Demand (kW)']
header_data = {
self._input_data['fileOut1']: header,
self._input_data['fileOut2']: ['Day', 'Operational Daily Emissions from Heat Pumps (g)', self._input_data['fileOut2']: ['Day', 'Operational Daily Emissions from Heat Pumps (g)',
'Operational Daily Emissions from Auxiliary Heater (g)'], 'Operational Daily Emissions from Auxiliary Heater (g)'],
self._input_data['fileOut3']: ['Month', 'Monthly Operational Costs of Heat Pumps (CAD)', self._input_data['fileOut3']: ['Month', 'Monthly Operational Costs of Heat Pumps (CAD)',
@ -102,7 +118,7 @@ class HeatPumpExport:
file_path = file_path.strip("'") file_path = file_path.strip("'")
df = pd.read_csv(file_path, header=None, sep='\s+') df = pd.read_csv(file_path, header=None, sep='\s+')
# ignore ambient temperature for air source series run # ignore ambient temperature for air source series run
if df.shape[1] > 25: if df.shape[1] > 25 and 'series' in str(self._template_path):
df.drop(columns=df.columns[-1], df.drop(columns=df.columns[-1],
axis=1, axis=1,
inplace=True) inplace=True)
@ -161,6 +177,8 @@ class HeatPumpExport:
with open(self._constants_path) as file: with open(self._constants_path) as file:
constants_dict = yaml.load(file, Loader=yaml.FullLoader) constants_dict = yaml.load(file, Loader=yaml.FullLoader)
for key, value in constants_dict.items(): for key, value in constants_dict.items():
if key in ['LowestPossibleLoadFlow', 'HighestPossibleLoadFlow'] and self._water_temp is None:
continue
self._input_data[key] = value self._input_data[key] = value
# compute water to water HP specific values # compute water to water HP specific values
if 55 <= self._input_data['HPSupTemp'] <= 60: if 55 <= self._input_data['HPSupTemp'] <= 60:
@ -206,15 +224,30 @@ class HeatPumpExport:
self._input_data["a10"] = a_coeff[9] self._input_data["a10"] = a_coeff[9]
self._input_data["a11"] = a_coeff[10] self._input_data["a11"] = a_coeff[10]
def _get_user_out_put(self): def _get_user_out_put(self) -> Union[Dict, None]:
""" """
Extracts monthly electricity demand and fossil fuel consumption Extracts monthly electricity demand and fossil fuel consumption
from output files generated by insel from output files generated by insel
:return: :return: Dict for json output
""" """
demand_data = 'fileOut8'
fossil_data = 'fileOut4'
fossil_index = 2
demand_index = 2
electricity_df = pd.read_csv(self._input_data['fileOut8'].strip("'")).iloc[:, 2] if self._output_path is None:
fossil_df = pd.read_csv(self._input_data['fileOut4'].strip("'")).iloc[:, 2] demand_data = 'fileOut10'
fossil_data = 'fileOut9'
demand_index = 5
electricity_df = pd.read_csv(self._input_data[demand_data].strip("'")).iloc[:, demand_index]
fossil_df = pd.read_csv(self._input_data[fossil_data].strip("'")).iloc[:, fossil_index]
if self._output_path is None:
return {
'hourly_electricity_demand': electricity_df.values.tolist(),
'daily_fossil_consumption': fossil_df.values.tolist()
}
data = [electricity_df, fossil_df] data = [electricity_df, fossil_df]
df = pd.concat(data, axis=1) df = pd.concat(data, axis=1)
@ -222,3 +255,5 @@ class HeatPumpExport:
s = pd.Series(["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "Total"]) s = pd.Series(["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "Total"])
df = df.set_index([s]) df = df.set_index([s])
df.to_csv(self._output_path) df.to_csv(self._output_path)

View File

@ -6,7 +6,7 @@ Copyright © 2022 Concordia CERC group
Project Coder Peter Yefi peteryefi@gmail.com Project Coder Peter Yefi peteryefi@gmail.com
""" """
from exports.energy_systems.heat_pump_export import HeatPumpExport from exports.energy_systems.heat_pump_export import HeatPumpExport
from typing import List, Tuple, Union from typing import List, Dict, Union
class WaterToWaterHPExport(HeatPumpExport): class WaterToWaterHPExport(HeatPumpExport):
@ -15,17 +15,19 @@ class WaterToWaterHPExport(HeatPumpExport):
after executing insel after executing insel
""" """
def __init__(self, base_path, city, output_path, sim_type): def __init__(self, base_path, city, output_path, sim_type, demand_path):
""" """
:param base_path: path to energy system files :param base_path: path to energy system files
:param city: the city object :param city: the city object
:param output_path: the file to hold insel simulation results :param output_path: the file to hold insel simulation results
:param sim_type: the simulation type to run: 1 for series, 0 for parallel :param sim_type: the simulation type to run: 1 for series, 0 for parallel
:param demand_path: path to hourly energy demand file
""" """
tmp_file = 'heat_pumps/w2w_series.txt' if sim_type == 0 else 'heat_pumps/w2w_parallel.txt' tmp_file = 'heat_pumps/w2w_series.txt' if sim_type == 0 else 'heat_pumps/w2w_parallel.txt'
template_path = (base_path / tmp_file) template_path = (base_path / tmp_file)
water_temp = (base_path / 'heat_pumps/wt_hourly3.txt') water_temp = (base_path / 'heat_pumps/wt_hourly3.txt')
super().__init__(base_path, city, output_path, template_path, water_temp) super().__init__(base_path=base_path, city=city, output_path=output_path, template=template_path,
demand_path=demand_path, water_temp=water_temp)
def _extract_model_coff(self, hp_model: str) -> Union[List, None]: def _extract_model_coff(self, hp_model: str) -> Union[List, None]:
""" """
@ -39,7 +41,7 @@ class WaterToWaterHPExport(HeatPumpExport):
return energy_system.water_to_water_hp.power_demand_coff return energy_system.water_to_water_hp.power_demand_coff
return None return None
def execute_insel(self, user_input, hp_model): def execute_insel(self, user_input, hp_model) -> Union[Dict, None]:
""" """
Runs insel and produces output files Runs insel and produces output files
Runs insel and write the necessary files Runs insel and write the necessary files
@ -50,4 +52,4 @@ class WaterToWaterHPExport(HeatPumpExport):
:return: :return:
""" """
pow_demand_coeff = self._extract_model_coff(hp_model) pow_demand_coeff = self._extract_model_coff(hp_model)
super(WaterToWaterHPExport, self)._run_insel(user_input, pow_demand_coeff, 'w2w.insel') return super(WaterToWaterHPExport, self)._run_insel(user_input, pow_demand_coeff, 'w2w.insel')

View File

@ -16,7 +16,8 @@ class EnergySystemsExportFactory:
Exports factory class for energy systems Exports factory class for energy systems
""" """
def __init__(self, city, user_input, hp_model, output_path, sim_type=0, data_type='heat', base_path=None): def __init__(self, city, user_input, hp_model, output_path, sim_type=0, data_type='heat', base_path=None,
demand_path=None):
""" """
:param city: the city object :param city: the city object
@ -26,7 +27,9 @@ class EnergySystemsExportFactory:
:param sim_type: the simulation type, 0 for series 1 for parallel :param sim_type: the simulation type, 0 for series 1 for parallel
:param data_type: indicates whether cooling or heating data is used :param data_type: indicates whether cooling or heating data is used
:param base_path: the data directory of energy systems :param base_path: the data directory of energy systems
:param demand_path: path to hourly energy dempand file
""" """
self._city = city self._city = city
if base_path is None: if base_path is None:
base_path = Path(Path(__file__).parent.parent / 'data/energy_systems') base_path = Path(Path(__file__).parent.parent / 'data/energy_systems')
@ -36,6 +39,7 @@ class EnergySystemsExportFactory:
self._data_type = data_type self._data_type = data_type
self._output_path = output_path self._output_path = output_path
self._sim_type = sim_type self._sim_type = sim_type
self._demand_path = demand_path
def _export_heat_pump(self, source): def _export_heat_pump(self, source):
""" """
@ -44,10 +48,10 @@ class EnergySystemsExportFactory:
:return: None :return: None
""" """
if source == 'air': if source == 'air':
AirSourceHPExport(self._base_path, self._city, self._output_path, self._sim_type)\ return AirSourceHPExport(self._base_path, self._city, self._output_path, self._sim_type, self._demand_path)\
.execute_insel(self._user_input, self._hp_model, self._data_type) .execute_insel(self._user_input, self._hp_model, self._data_type)
elif source == 'water': elif source == 'water':
WaterToWaterHPExport(self._base_path, self._city, self._output_path, self._sim_type)\ return WaterToWaterHPExport(self._base_path, self._city, self._output_path, self._sim_type, self._demand_path)\
.execute_insel(self._user_input, self._hp_model) .execute_insel(self._user_input, self._hp_model)
def export(self, source='air'): def export(self, source='air'):

View File

@ -12,6 +12,21 @@ from city_model_structure.energy_systems.air_source_hp import AirSourceHP
from exports.energy_systems_factory import EnergySystemsExportFactory from exports.energy_systems_factory import EnergySystemsExportFactory
import os import os
# User defined paramenters
user_input = {
'StartYear': 2020,
'EndYear': 2021,
'MaximumHPEnergyInput': 8000,
'HoursOfStorageAtMaxDemand': 1,
'BuildingSuppTemp': 40,
'TemperatureDifference': 15,
'FuelLHV': 47100,
'FuelPrice': 0.12,
'FuelEF': 1887,
'FuelDensity': 0.717,
'HPSupTemp': 60
}
class TestEnergySystemsFactory(TestCase): class TestEnergySystemsFactory(TestCase):
""" """
@ -34,27 +49,20 @@ class TestEnergySystemsFactory(TestCase):
self.assertEqual(self._city.energy_systems[0].air_source_hp.model, '012') self.assertEqual(self._city.energy_systems[0].air_source_hp.model, '012')
self.assertEqual(self._city.energy_systems[16].air_source_hp.model, '140') self.assertEqual(self._city.energy_systems[16].air_source_hp.model, '140')
def test_air_source_heat_pump_export(self): def test_air_source_series_heat_pump_export(self):
# User defined paramenters EnergySystemsExportFactory(city=self._city, user_input=user_input, hp_model='012',
user_input = { output_path=self._output_path).export()
'StartYear': 2020,
'EndYear': 2021,
'MaximumHPEnergyInput': 8000,
'HoursOfStorageAtMaxDemand': 1,
'BuildingSuppTemp': 40,
'TemperatureDifference': 15,
'FuelLHV': 47100,
'FuelPrice': 0.12,
'FuelEF': 1887,
'FuelDensity': 0.717,
'HPSupTemp': 60
}
EnergySystemsExportFactory(self._city, user_input, '012', self._output_path).export()
df = pd.read_csv(self._output_path) df = pd.read_csv(self._output_path)
self.assertEqual(df.shape, (13, 3)) self.assertEqual(df.shape, (13, 3))
self.assertEqual(df.iloc[0, 1], 1867715.88) self.assertEqual(df.iloc[0, 1], 1867715.88)
def test_air_source_parallel_heat_pump_export(self):
output = EnergySystemsExportFactory(city=self._city, user_input=user_input, hp_model='018',
output_path=None, sim_type=1).export()
self.assertEqual(output["hourly_electricity_demand"][0], 38748.5625)
self.assertIsNotNone(output["daily_fossil_consumption"])
self.assertEqual(len(output["hourly_electricity_demand"]), 8760)
def tearDown(self) -> None: def tearDown(self) -> None:
try: try:
os.remove(self._output_path) os.remove(self._output_path)

View File

@ -13,6 +13,21 @@ import pandas as pd
import os import os
# User defined paramenters
user_input = {
'StartYear': 2020,
'EndYear': 2021,
'MaximumHPEnergyInput': 8000,
'HoursOfStorageAtMaxDemand': 1,
'BuildingSuppTemp': 40,
'TemperatureDifference': 15,
'FuelLHV': 47100,
'FuelPrice': 0.12,
'FuelEF': 1887,
'FuelDensity': 0.717,
'HPSupTemp': 60
}
class TestEnergySystemsFactory(TestCase): class TestEnergySystemsFactory(TestCase):
""" """
@ -35,27 +50,21 @@ class TestEnergySystemsFactory(TestCase):
self.assertEqual(self._city.energy_systems[0].water_to_water_hp.model, 'ClimateMaster 156 kW') self.assertEqual(self._city.energy_systems[0].water_to_water_hp.model, 'ClimateMaster 156 kW')
self.assertEqual(self._city.energy_systems[2].water_to_water_hp.model, 'ClimateMaster 335 kW') self.assertEqual(self._city.energy_systems[2].water_to_water_hp.model, 'ClimateMaster 335 kW')
def test_water_to_water_heat_pump_export(self): def test_water_to_water_series_heat_pump_export(self):
# User defined paramenters
user_input = {
'StartYear': 2020,
'EndYear': 2021,
'MaximumHPEnergyInput': 8000,
'HoursOfStorageAtMaxDemand': 1,
'BuildingSuppTemp': 40,
'TemperatureDifference': 15,
'FuelLHV': 47100,
'FuelPrice': 0.12,
'FuelEF': 1887,
'FuelDensity': 0.717,
'HPSupTemp': 60
}
EnergySystemsExportFactory(self._city, user_input, 'ClimateMaster 156 kW', self._output_path).export('water') EnergySystemsExportFactory(city=self._city, user_input=user_input, hp_model='ClimateMaster 156 kW',
output_path=self._output_path).export('water')
df = pd.read_csv(self._output_path) df = pd.read_csv(self._output_path)
print(df.shape) self.assertEqual(df.shape, (13, 3))
#self.assertEqual(df.shape, (13, 3)) self.assertEqual(df.iloc[0, 1], 1162387.5)
#self.assertEqual(df.iloc[0, 1], 3045398.0)
def test_water_to_water_parallel_heat_pump_export(self):
EnergySystemsExportFactory(city=self._city, user_input=user_input, hp_model='ClimateMaster 256 kW',
output_path=self._output_path, sim_type=1).export('water')
df = pd.read_csv(self._output_path)
self.assertEqual(df.shape, (13, 3))
self.assertEqual(df.iloc[0, 1], 1031544.62)
def tearDown(self) -> None: def tearDown(self) -> None:
try: try: