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
TESDiameter: 5
AuxHeaterEfficiency: 0.9
HPNominalCapacity: 256
# These come from the data model according to other student's work
ElecGridEF: 0.5
ElectricityPrice: 0.073
# Water to Water HP constants
HPNominalCapacity: 256
LowestPossibleLoadFlow: 4.73
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
"""
from exports.energy_systems.heat_pump_export import HeatPumpExport
from typing import List, Tuple, Union
from typing import List, Dict, Union
class AirSourceHPExport(HeatPumpExport):
@ -15,17 +15,18 @@ class AirSourceHPExport(HeatPumpExport):
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 city: the city object
: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 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'
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]:
"""
@ -43,7 +44,7 @@ class AirSourceHPExport(HeatPumpExport):
return energy_system.air_source_hp.cooling_capacity_coff
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 write the necessary files
@ -54,7 +55,6 @@ class AirSourceHPExport(HeatPumpExport):
:param data_type: a string that indicates whether
insel should run for heat or cooling performance
:return:
:return:
"""
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
"""
import os
from typing import List, Tuple, Union, Dict
from typing import List, Union, Dict
import yaml
from string import Template
import pandas as pd
@ -17,18 +17,18 @@ class HeatPumpExport:
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._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')
self._demand_path = (base_path / 'heat_pumps/demand.txt') if demand_path is None else demand_path
self._city = city
self._input_data = None
self._base_path = base_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
:param user_input: a dictionary containing the user
@ -60,7 +60,7 @@ class HeatPumpExport:
# Writer headers to csv output files generated by insel
self._write_insel_output_headers()
# User output
self._get_user_out_put()
return self._get_user_out_put()
except IOError as err:
print("I/O exception: {}".format(err))
finally:
@ -72,17 +72,33 @@ class HeatPumpExport:
Write headers to the various csv file generated by insel
:return:
"""
header = [
'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)',
'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 Energy Content (kWh)', 'TES Energy Content Variation (kWh)',
'Auxiliary Heater Fuel Flow Rate (kg/s)', 'Auxiliary Heater Energy Input (kW)',
'HP Operational Cost (CAD)', 'Auxiliary Heater Operational Cost (CAD)',
'Operational CO2 Emissions of HP (g)',
'Operational CO2 Emissions of Auxiliary Heater (g)',
'Return Temperature', 'Demand (kW)']
header_data = {
self._input_data['fileOut1']: ['Year', ' Month', ' Day', 'Hour', 'Minute', 'HP Heat Output (kW)',
'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 Node 3 Temperature', 'TES Node 4 Temperature', 'TES Energy Content (J)',
'TES Energy Content (kWh)', 'TES Energy Content Variation (kWh)',
'Auxiliary Heater Fuel Flow Rate (kg/s)', 'Auxiliary Heater Energy Input (kW)',
'HP Operational Cost (CAD)', 'Auxiliary Heater Operational Cost (CAD)',
'Operational CO2 Emissions of HP (g)',
'Operational CO2 Emissions of Auxiliary Heater (g)',
'Return Temperature', 'Demand (kW)'],
self._input_data['fileOut1']: header,
self._input_data['fileOut2']: ['Day', 'Operational Daily Emissions from Heat Pumps (g)',
'Operational Daily Emissions from Auxiliary Heater (g)'],
self._input_data['fileOut3']: ['Month', 'Monthly Operational Costs of Heat Pumps (CAD)',
@ -102,7 +118,7 @@ class HeatPumpExport:
file_path = file_path.strip("'")
df = pd.read_csv(file_path, header=None, sep='\s+')
# 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],
axis=1,
inplace=True)
@ -161,6 +177,8 @@ class HeatPumpExport:
with open(self._constants_path) as file:
constants_dict = yaml.load(file, Loader=yaml.FullLoader)
for key, value in constants_dict.items():
if key in ['LowestPossibleLoadFlow', 'HighestPossibleLoadFlow'] and self._water_temp is None:
continue
self._input_data[key] = value
# compute water to water HP specific values
if 55 <= self._input_data['HPSupTemp'] <= 60:
@ -206,15 +224,30 @@ class HeatPumpExport:
self._input_data["a10"] = a_coeff[9]
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
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]
fossil_df = pd.read_csv(self._input_data['fileOut4'].strip("'")).iloc[:, 2]
if self._output_path is None:
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]
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"])
df = df.set_index([s])
df.to_csv(self._output_path)

View File

@ -6,7 +6,7 @@ Copyright © 2022 Concordia CERC group
Project Coder Peter Yefi peteryefi@gmail.com
"""
from exports.energy_systems.heat_pump_export import HeatPumpExport
from typing import List, Tuple, Union
from typing import List, Dict, Union
class WaterToWaterHPExport(HeatPumpExport):
@ -15,17 +15,19 @@ class WaterToWaterHPExport(HeatPumpExport):
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 city: the city object
: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 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'
template_path = (base_path / tmp_file)
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]:
"""
@ -39,7 +41,7 @@ class WaterToWaterHPExport(HeatPumpExport):
return energy_system.water_to_water_hp.power_demand_coff
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 write the necessary files
@ -50,4 +52,4 @@ class WaterToWaterHPExport(HeatPumpExport):
:return:
"""
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
"""
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
@ -26,7 +27,9 @@ class EnergySystemsExportFactory:
:param sim_type: the simulation type, 0 for series 1 for parallel
:param data_type: indicates whether cooling or heating data is used
:param base_path: the data directory of energy systems
:param demand_path: path to hourly energy dempand file
"""
self._city = city
if base_path is None:
base_path = Path(Path(__file__).parent.parent / 'data/energy_systems')
@ -36,6 +39,7 @@ class EnergySystemsExportFactory:
self._data_type = data_type
self._output_path = output_path
self._sim_type = sim_type
self._demand_path = demand_path
def _export_heat_pump(self, source):
"""
@ -44,10 +48,10 @@ class EnergySystemsExportFactory:
:return: None
"""
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)
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)
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
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):
"""
@ -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[16].air_source_hp.model, '140')
def test_air_source_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, '012', self._output_path).export()
def test_air_source_series_heat_pump_export(self):
EnergySystemsExportFactory(city=self._city, user_input=user_input, hp_model='012',
output_path=self._output_path).export()
df = pd.read_csv(self._output_path)
self.assertEqual(df.shape, (13, 3))
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:
try:
os.remove(self._output_path)

View File

@ -13,6 +13,21 @@ import pandas as pd
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):
"""
@ -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[2].water_to_water_hp.model, 'ClimateMaster 335 kW')
def test_water_to_water_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
}
def test_water_to_water_series_heat_pump_export(self):
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)
print(df.shape)
#self.assertEqual(df.shape, (13, 3))
#self.assertEqual(df.iloc[0, 1], 3045398.0)
self.assertEqual(df.shape, (13, 3))
self.assertEqual(df.iloc[0, 1], 1162387.5)
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:
try: