forked from s_ranjbar/city_retrofit
Added heat pump simulation persistence
This commit is contained in:
parent
7974317d13
commit
27456ffddd
|
@ -5,6 +5,7 @@ Copyright © 2022 Concordia CERC group
|
|||
Project CoderPeter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
from persistence import CityRepo
|
||||
from persistence import HeatPumpSimulationRepo
|
||||
|
||||
|
||||
class DBFactory:
|
||||
|
@ -15,6 +16,7 @@ class DBFactory:
|
|||
def __init__(self, city, db_name, app_env):
|
||||
self._city = city
|
||||
self._city_repo = CityRepo(db_name=db_name, app_env=app_env)
|
||||
self._hp_simulation_repo = HeatPumpSimulationRepo(db_name=db_name, app_env=app_env)
|
||||
|
||||
def get_city(self, city_id):
|
||||
"""
|
||||
|
@ -30,3 +32,16 @@ class DBFactory:
|
|||
"""
|
||||
return self._city_repo.get_by_name(city_name)
|
||||
|
||||
def get_hp_simulation(self, hp_sim_id: int):
|
||||
"""
|
||||
Retrieve a single heat pump simulation from postgres
|
||||
:param hp_sim_id: the id of the heat pump to get
|
||||
"""
|
||||
return self._hp_simulation_repo.get_by_id(hp_sim_id)
|
||||
|
||||
def get_hp_simulation_by_city(self, city_id: int):
|
||||
"""
|
||||
Retrieve a single city from postgres
|
||||
:param city_id: the id of the city
|
||||
"""
|
||||
return self._hp_simulation_repo.get_by_city(city_id)
|
||||
|
|
|
@ -56,7 +56,7 @@ class HeatPumpExport:
|
|||
insel_file_handler.write(insel_template)
|
||||
# Now run insel
|
||||
self._delete_existing_output_files()
|
||||
os.system('insel {}'.format(insel_file))
|
||||
os.system('/usr/local/bin/insel {}'.format(insel_file))
|
||||
# Writer headers to csv output files generated by insel
|
||||
self._write_insel_output_headers()
|
||||
# User output
|
||||
|
@ -230,26 +230,20 @@ class HeatPumpExport:
|
|||
from output files generated by insel
|
||||
:return: Dict for json output
|
||||
"""
|
||||
demand_data = 'fileOut8'
|
||||
fossil_data = 'fileOut4'
|
||||
fossil_index = 2
|
||||
demand_index = 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]
|
||||
monthly_electricity_df = pd.read_csv(self._input_data['fileOut8'].strip("'")).iloc[:, 2]
|
||||
monthly_fossil_df = pd.read_csv(self._input_data['fileOut4'].strip("'")).iloc[:, 2]
|
||||
|
||||
if self._output_path is None:
|
||||
return {
|
||||
'hourly_electricity_demand': electricity_df.values.tolist(),
|
||||
'daily_fossil_consumption': fossil_df.values.tolist()
|
||||
'hourly_electricity_demand': pd.read_csv(self._input_data['fileOut10'].strip("'")).iloc[:, 5].tolist(),
|
||||
'monthly_electricity_demand': monthly_electricity_df.tolist(),
|
||||
'daily_electricity_demand': pd.read_csv(self._input_data['fileOut6'].strip("'")).iloc[:, 2].tolist(),
|
||||
'daily_fossil_consumption': pd.read_csv(self._input_data['fileOut9'].strip("'")).iloc[:, 2].tolist(),
|
||||
'monthly_fossil_consumption': monthly_fossil_df.tolist()
|
||||
}
|
||||
|
||||
data = [electricity_df, fossil_df]
|
||||
data = [monthly_electricity_df, monthly_fossil_df]
|
||||
df = pd.concat(data, axis=1)
|
||||
df = pd.concat([df, df.agg(['sum'])])
|
||||
s = pd.Series(["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "Total"])
|
||||
|
|
|
@ -5,6 +5,8 @@ Copyright © 2022 Concordia CERC group
|
|||
Project CoderPeter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
from persistence import CityRepo
|
||||
from persistence import HeatPumpSimulationRepo
|
||||
from typing import Dict
|
||||
|
||||
|
||||
class DBFactory:
|
||||
|
@ -15,6 +17,7 @@ class DBFactory:
|
|||
def __init__(self, city, db_name, app_env):
|
||||
self._city = city
|
||||
self._city_repo = CityRepo(db_name=db_name, app_env=app_env)
|
||||
self._hp_simulation_repo = HeatPumpSimulationRepo(db_name=db_name, app_env=app_env)
|
||||
|
||||
def persist_city(self):
|
||||
"""
|
||||
|
@ -37,3 +40,19 @@ class DBFactory:
|
|||
"""
|
||||
self._city_repo.delete_city(city_id)
|
||||
|
||||
def persist_hp_simulation(self, hp_simulation_data: Dict, city_id: int):
|
||||
"""
|
||||
Persist heat pump simulation results
|
||||
:param hp_simulation_data: the simulation results
|
||||
:param city_id: the city object used in running the simulation
|
||||
:return: HeatPumpSimulation object
|
||||
"""
|
||||
return self._hp_simulation_repo.insert(hp_simulation_data, city_id)
|
||||
|
||||
def delete_hp_simulation(self, hp_sim_id):
|
||||
"""
|
||||
Deletes a single heat pump simulation from postgres
|
||||
:param hp_sim_id: the id of the heat pump simulation to get
|
||||
"""
|
||||
self._hp_simulation_repo.delete_hp_simulation(hp_sim_id)
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from .base_repo import BaseRepo
|
||||
from .repositories.city_repo import CityRepo
|
||||
from .repositories.building_repo import BuildingRepo
|
||||
from .repositories.heat_pump_simulation_repo import HeatPumpSimulationRepo
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from .building import Building
|
||||
from .city import City
|
||||
from .heat_pump_simulation import HeatPumpSimulation
|
||||
|
||||
from .heat_pump_simulation import SimulationTypes
|
||||
from .heat_pump_simulation import HeatPumpTypes
|
||||
|
|
|
@ -5,9 +5,11 @@ Copyright © 2022 Concordia CERC group
|
|||
Project Coder Peter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
|
||||
from sqlalchemy import Column, Integer, String, Sequence, PickleType, Float
|
||||
from sqlalchemy import Column, Integer, String, Sequence
|
||||
from sqlalchemy import DateTime, PickleType, Float
|
||||
from persistence.db_config import Base
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
import datetime
|
||||
|
||||
|
||||
class City(Base):
|
||||
|
@ -27,4 +29,5 @@ class City(Base):
|
|||
upper_corner = Column(JSONB, nullable=False)
|
||||
hub_release = Column(String, nullable=False)
|
||||
city_version = Column(Integer, nullable=False)
|
||||
created = Column(DateTime, default=datetime.datetime.utcnow)
|
||||
|
||||
|
|
|
@ -5,18 +5,20 @@ Copyright © 2022 Concordia CERC group
|
|||
Project Coder Peter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
|
||||
from sqlalchemy import Column, Integer, String, Sequence, Float, ForeignKey, Enum
|
||||
from sqlalchemy import Column, Integer, String, Sequence
|
||||
from sqlalchemy import Enum, ForeignKey, Float, DateTime
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
from persistence.db_config import Base
|
||||
from enum import Enum
|
||||
import enum
|
||||
import datetime
|
||||
|
||||
|
||||
class SimulationTypes(Enum):
|
||||
class SimulationTypes(enum.Enum):
|
||||
Parallel = 'PARALLEL'
|
||||
Series = 'SERIES'
|
||||
|
||||
|
||||
class HeatPumpTypes(Enum):
|
||||
class HeatPumpTypes(enum.Enum):
|
||||
Air = 'Air Source'
|
||||
Water = 'Water to Water'
|
||||
|
||||
|
@ -26,6 +28,7 @@ class HeatPumpSimulation(Base):
|
|||
|
||||
Attributes:
|
||||
city_id, A reference to the city which was used to run this simulation.
|
||||
hourly_electricity_demand, A JSON object that has hours and their electricity demand
|
||||
daily_electricity_demand, A JSON object that has days and their electricity demand
|
||||
monthly_electricity_demand, A JSON object that has months and their electricity demand
|
||||
daily_fossil_fuel_consumption, A JSON object that has days and fossil fuel consumption
|
||||
|
@ -51,6 +54,7 @@ class HeatPumpSimulation(Base):
|
|||
id = Column(Integer, Sequence('hp_simulation_id_seq'), primary_key=True)
|
||||
city_id = Column(Integer, ForeignKey('city.id'), nullable=False)
|
||||
daily_electricity_demand = Column(JSONB, nullable=False)
|
||||
hourly_electricity_demand = Column(JSONB, nullable=False)
|
||||
daily_fossil_fuel_consumption = Column(JSONB, nullable=False)
|
||||
monthly_fossil_fuel_consumption = Column(JSONB, nullable=False)
|
||||
monthly_electricity_demand = Column(JSONB, nullable=False)
|
||||
|
@ -68,4 +72,5 @@ class HeatPumpSimulation(Base):
|
|||
fuel_efficiency = Column(Float, nullable=False)
|
||||
fuel_density = Column(Float, nullable=False)
|
||||
hp_supply_temp = Column(Float, nullable=False)
|
||||
created = Column(DateTime, default=datetime.datetime.utcnow)
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ class HeatPumpSimulationRepo(BaseRepo):
|
|||
if city is None:
|
||||
return {'message': 'city not found in database'}
|
||||
|
||||
try:
|
||||
hp_simulation = HeatPumpSimulation()
|
||||
hp_simulation.city_id = city_id
|
||||
hp_simulation.end_year = hp_simulation_data["EndYear"]
|
||||
|
@ -53,19 +54,23 @@ class HeatPumpSimulationRepo(BaseRepo):
|
|||
hp_simulation.fuel_density = hp_simulation_data["FuelDensity"]
|
||||
hp_simulation.hp_supply_temp = hp_simulation_data["HPSupTemp"]
|
||||
hp_simulation.daily_electricity_demand = hp_simulation_data["DailyElectricityDemand"]
|
||||
hp_simulation.hourly_electricity_demand = hp_simulation_data["HourlyElectricityDemand"]
|
||||
hp_simulation.monthly_electricity_demand = hp_simulation_data["MonthlyElectricityDemand"]
|
||||
hp_simulation.daily_fossil_fuel_consumption = hp_simulation_data["DailyFossilFuelConsumption"]
|
||||
hp_simulation.monthly_fossil_fuel_consumption = hp_simulation_data["MonthlyFossilFuelConsumption"]
|
||||
hp_simulation.simulation_type = hp_simulation_data["SimulationType"]
|
||||
hp_simulation.heat_pump_model = hp_simulation_data["HeatPumpModel"]
|
||||
hp_simulation.heat_pump_type = hp_simulation_data["HeatPumpType"]
|
||||
|
||||
try:
|
||||
# Persist heat pump simulation data
|
||||
self.session.add(hp_simulation)
|
||||
self.session.flush()
|
||||
self.session.commit()
|
||||
return hp_simulation
|
||||
|
||||
except SQLAlchemyError as err:
|
||||
print(f'Error while saving heat pump simulation data: {err}')
|
||||
except KeyError as err:
|
||||
print(f'A required field is missing in your heat pump simulation dictionary: {err}')
|
||||
|
||||
def get_by_id(self, hp_simulation_id: int) -> HeatPumpSimulation:
|
||||
"""
|
||||
|
|
|
@ -35,12 +35,12 @@ class TestDBFactory(TestCase):
|
|||
self._export_db_factory = ExportDBFactory(city=self.city, db_name='hub_test', app_env='TEST')
|
||||
|
||||
def test_save_city(self):
|
||||
self._saved_city = self._db_factory.persist_city()
|
||||
self.assertEqual(self._saved_city.name, 'Montréal')
|
||||
pickled_city = loads(self._saved_city.city)
|
||||
saved_city = self._db_factory.persist_city()
|
||||
self.assertEqual(saved_city.name, 'Montréal')
|
||||
pickled_city = loads(saved_city.city)
|
||||
self.assertEqual(len(pickled_city.buildings), 10)
|
||||
self.assertEqual(pickled_city.buildings[0].floor_area, 1990.9913970530033)
|
||||
self._db_factory.delete_city(self._saved_city.id)
|
||||
self._db_factory.delete_city(saved_city.id)
|
||||
|
||||
def test_save_same_city_with_same_hub_version(self):
|
||||
first_city = self._db_factory.persist_city()
|
||||
|
|
103
unittests/test_heat_pump_simulation.py
Normal file
103
unittests/test_heat_pump_simulation.py
Normal file
|
@ -0,0 +1,103 @@
|
|||
"""
|
||||
Test EnergySystemsFactory and various heatpump models
|
||||
SPDX - License - Identifier: LGPL - 3.0 - or -later
|
||||
Copyright © 2022 Concordia CERC group
|
||||
Project Coder Peter Yefi peteryefi@gmail.com
|
||||
"""
|
||||
from unittest import TestCase
|
||||
from imports.geometry_factory import GeometryFactory
|
||||
from imports.energy_systems_factory import EnergySystemsFactory
|
||||
from exports.energy_systems_factory import EnergySystemsExportFactory
|
||||
from imports.db_factory import DBFactory
|
||||
from exports.db_factory import DBFactory as ExportDBFactory
|
||||
from persistence.db_config import BaseConfiguration
|
||||
from sqlalchemy import create_engine
|
||||
from persistence.models import City
|
||||
from persistence.models import SimulationTypes
|
||||
from persistence.models import HeatPumpTypes
|
||||
from persistence.models import HeatPumpSimulation
|
||||
|
||||
# User defined paramenters
|
||||
hp_sim_data = {
|
||||
'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 TestHeatPumpSimulation(TestCase):
|
||||
"""
|
||||
Heat pump simulation test cases
|
||||
"""
|
||||
|
||||
def setUp(self) -> None:
|
||||
"""
|
||||
Test setup
|
||||
:return: None
|
||||
"""
|
||||
# Create test tables if they do not exit
|
||||
config = BaseConfiguration(db_name='hub_test', app_env='TEST')
|
||||
engine = create_engine(config.conn_string())
|
||||
City.__table__.create(bind=engine, checkfirst=True)
|
||||
HeatPumpSimulation.__table__.create(bind=engine, checkfirst=True)
|
||||
|
||||
city_file = "../unittests/tests_data/C40_Final.gml"
|
||||
self._city = GeometryFactory('citygml', city_file).city
|
||||
EnergySystemsFactory('air source hp', self._city).enrich()
|
||||
|
||||
self._db_factory = DBFactory(city=self._city, db_name='hub_test', app_env='TEST')
|
||||
self._export_db_factory = ExportDBFactory(city=self._city, db_name='hub_test', app_env='TEST')
|
||||
|
||||
def test_heat_pump_simulation_persistence(self):
|
||||
output = EnergySystemsExportFactory(city=self._city, user_input=hp_sim_data, hp_model='018',
|
||||
output_path=None, sim_type=1).export()
|
||||
hp_sim_data["HeatPumpModel"] = '018'
|
||||
hp_sim_data["SimulationType"] = SimulationTypes.Parallel
|
||||
hp_sim_data["HeatPumpType"] = HeatPumpTypes.Air
|
||||
hp_sim_data["HourlyElectricityDemand"] = output["hourly_electricity_demand"]
|
||||
hp_sim_data["DailyElectricityDemand"] = output["daily_electricity_demand"]
|
||||
hp_sim_data["MonthlyElectricityDemand"] = output["monthly_electricity_demand"]
|
||||
hp_sim_data["DailyFossilFuelConsumption"] = output["daily_fossil_consumption"]
|
||||
hp_sim_data["MonthlyFossilFuelConsumption"] = output["monthly_fossil_consumption"]
|
||||
|
||||
saved_city = self._db_factory.persist_city()
|
||||
hp_sim = self._db_factory.persist_hp_simulation(hp_sim_data, saved_city.id)
|
||||
self.assertEqual(hp_sim.heat_pump_type, HeatPumpTypes.Air)
|
||||
self.assertEqual(hp_sim.simulation_type, SimulationTypes.Parallel)
|
||||
self.assertEqual(hp_sim.fuel_efficiency, hp_sim_data["FuelEF"])
|
||||
self.assertEqual(hp_sim.monthly_electricity_demand, output["monthly_electricity_demand"])
|
||||
self._db_factory.delete_hp_simulation(hp_sim.id)
|
||||
self._db_factory.delete_city(saved_city.id)
|
||||
|
||||
def test_get_heat_pump_simulation_by_city(self):
|
||||
output = EnergySystemsExportFactory(city=self._city, user_input=hp_sim_data, hp_model='012',
|
||||
output_path=None, sim_type=0).export()
|
||||
hp_sim_data["HeatPumpModel"] = '012'
|
||||
hp_sim_data["SimulationType"] = SimulationTypes.Series
|
||||
hp_sim_data["HeatPumpType"] = HeatPumpTypes.Air
|
||||
hp_sim_data["HourlyElectricityDemand"] = output["hourly_electricity_demand"]
|
||||
hp_sim_data["DailyElectricityDemand"] = output["daily_electricity_demand"]
|
||||
hp_sim_data["MonthlyElectricityDemand"] = output["monthly_electricity_demand"]
|
||||
hp_sim_data["DailyFossilFuelConsumption"] = output["daily_fossil_consumption"]
|
||||
hp_sim_data["MonthlyFossilFuelConsumption"] = output["monthly_fossil_consumption"]
|
||||
|
||||
saved_city = self._db_factory.persist_city()
|
||||
self._db_factory.persist_hp_simulation(hp_sim_data, saved_city.id)
|
||||
|
||||
# retrieved saved simulation by city id
|
||||
hp_sim = self._export_db_factory.get_hp_simulation_by_city(saved_city.id)
|
||||
self.assertEqual(hp_sim[0].heat_pump_type, HeatPumpTypes.Air)
|
||||
self.assertEqual(hp_sim[0].simulation_type, SimulationTypes.Series)
|
||||
self.assertEqual(hp_sim[0].fuel_price, hp_sim_data["FuelPrice"])
|
||||
self.assertEqual(hp_sim[0].hourly_electricity_demand, output["hourly_electricity_demand"])
|
||||
|
||||
self._db_factory.delete_hp_simulation(hp_sim[0].id)
|
||||
self._db_factory.delete_city(saved_city.id)
|
Loading…
Reference in New Issue
Block a user