"""
This module includes functions to model setpoint of the thermal zone
"""
__author__ = "Enrico Prataviera"
__credits__ = ["Enrico Prataviera"]
__license__ = "MIT"
__version__ = "0.1"
__maintainer__ = "Enrico Prataviera"
import logging
import numpy as np
from eureca_building.schedule_properties import setpoint_prop
from eureca_building.schedule import Schedule
from eureca_building.fluids_properties import vapour_properties
from eureca_building.exceptions import (
SetpointTypeNotAllowed,
)
# TODO: implement interface for methods to be implemented
# https://realpython.com/python-interface/
[docs]class Setpoint:
"""Setpoint class
"""
[docs] def __init__(
self,
name: str,
setpoint_type: str,
tag: str = None,
):
f"""Parent class for some inherited SetpointObjects
Parameters
----------
name : str
name
setpoint_type : float
type from: {setpoint_prop.keys()}
tag : str, default None
a tag to define the type of internal load
"""
self.name = name
self.setpoint_type = setpoint_type
self.tag = tag
@property
def setpoint_type(self):
return self._setpoint_type
@setpoint_type.setter
def setpoint_type(self, value):
try:
value = str(value)
except ValueError:
raise ValueError(f"Setpoint {self.name}, schedule_type is not a str: {value}")
if value not in setpoint_prop.keys():
raise SetpointTypeNotAllowed(
f"Setpoint {self.name}, {value} schedule_type not allowed. Chose from: {setpoint_prop.keys()}")
self._setpoint_type = value
# def get_convective_load(self, *args, **kwarg) -> np.array:
# raise NotImplementedError(
# f"""
# You must override the get_convective_load method for each class inherited from InternalLoad
# Return value must be a np.array
# """
# )
[docs]class SetpointDualBand(Setpoint):
[docs] def __init__(self,
name: str,
setpoint_type: str,
schedule_lower: Schedule,
schedule_upper: Schedule,
tag: str = None, ):
f"""Inherited from the Setpoint class. Takes two schedules (a lower and upper boundary), to create a dual band setpoint
Uses properties to check if lower and upper boundaries intersect
Parameters
----------
name : str
name
setpoint_type : float
type from: {setpoint_prop.keys()}
schedule_lower : eureca_building.schedule.Schedule
Schedule object to define the lower boundary
schedule_upper : eureca_building.schedule.Schedule
Schedule object to define the upper boundary
tag : str, default None
a tag to define the type of internal load
"""
super().__init__(name, setpoint_type, tag)
self.schedule_lower = schedule_lower
self.schedule_upper = schedule_upper
# Check if setpoints schedules are not intersecting
if np.any(np.greater_equal(self.schedule_lower.schedule, self.schedule_upper.schedule)):
raise ValueError(f"Setpoint {self.name}, lower schedule higher than upper schedule.")
@property
def schedule_lower(self):
return self._schedule_lower
@schedule_lower.setter
def schedule_lower(self, value):
if not isinstance(value, Schedule):
raise ValueError(f"Setpoint {self.name}, lower schedule type not Schedule: {type(value)}")
if np.any(np.less(value.schedule, setpoint_prop[self.setpoint_type]['limit'][0])):
logging.warning(
f"Setpoint {self.name}, lower schedule goes below {setpoint_prop[self.setpoint_type]['limit'][0]} {setpoint_prop[self.setpoint_type]['unit']}")
self._schedule_lower = value
@property
def schedule_upper(self):
return self._schedule_upper
@schedule_upper.setter
def schedule_upper(self, value):
if not isinstance(value, Schedule):
raise ValueError(f"Setpoint {self.name}, lower schedule type not Schedule: {type(value)}")
if np.any(np.greater(value.schedule, setpoint_prop[self.setpoint_type]['limit'][1])):
logging.warning(
f"Setpoint {self.name}, lower schedule goes above {setpoint_prop[self.setpoint_type]['limit'][1]} {setpoint_prop[self.setpoint_type]['unit']}")
self._schedule_upper = value