Source code for ladybug_comfort.parameter.pmv

# coding=utf-8
"""Parameters for specifying acceptable thermal conditions using the PMV model."""
from __future__ import division
import re

from ._base import ComfortParameter
from ..pmv import ppd_threshold_from_comfort_class


[docs] class PMVParameter(ComfortParameter): """Parameters of PMV comfort. Args: ppd_comfort_thresh: A number between 5 and 100 that represents the upper threshold of PPD that is considered acceptable. Default is 10, which characterizes most buildings in the ASHRAE-55 and EN-15251 standards. humid_ratio_upper: A number between 0 and 1 indicating the upper limit of humidity ratio that is considered acceptable. Default is 1 for essentially no limit. humid_ratio_lower: A number between 0 and 1 indicating the lower limit of humidity ratio considered acceptable. Default is 0 for essentially no limit. still_air_threshold: The air speed threshold in m/s at which the standard effective temperature (SET) model will be used to correct for the cooling effect of elevated air speeds. Default is 0.1 m/s, which is the limit according to ASHRAE-55. Properties: * ppd_comfort_thresh * humid_ratio_upper * humid_ratio_low * still_air_threshold """ _model = 'Predicted Mean Vote' __slots__ = ('_ppd_thresh', '_hr_upper', '_hr_lower', '_still_thresh') def __init__(self, ppd_comfort_thresh=None, humid_ratio_upper=None, humid_ratio_lower=None, still_air_threshold=None): """Initialize PMV Parameters.""" self.ppd_comfort_thresh = \ ppd_comfort_thresh if ppd_comfort_thresh is not None else 10 self._hr_upper = humid_ratio_upper if humid_ratio_upper is not None else 1 self._hr_lower = humid_ratio_lower if humid_ratio_lower is not None else 0 self._still_thresh = \ still_air_threshold if still_air_threshold is not None else 0.1 assert 0.008 <= self._hr_upper <= 1, \ 'humid_ratio_upper must be between 0.008 and 1. Got {}'.format( self._hr_upper) assert 0 <= self._hr_lower <= 0.005, \ 'humid_ratio_lower must be between 0 and 0.005. Got {}'.format( self._hr_lower) assert 0 <= self._still_thresh, \ 'still_air_threshold must be greater than 0. Got {}'.format( self._still_thresh)
[docs] @classmethod def from_dict(cls, data): """Create a PMVParameter object from a dictionary. Args: data: A PMVParameter dictionary in following the format below. .. code-block:: python { 'type': 'PMVParameter', 'ppd_comfort_thresh': 20, 'humid_ratio_upper': 0.12, 'humid_ratio_lower': 0, 'still_air_threshold': 0.2 } """ assert data['type'] == 'PMVParameter', \ 'Expected PMVParameter dictionary. Got {}.'.format(data['type']) ppd_comfort_thresh = data['ppd_comfort_thresh'] if \ 'ppd_comfort_thresh' in data else 10 humid_ratio_upper = data['humid_ratio_upper'] if \ 'humid_ratio_upper' in data else 1 humid_ratio_lower = data['humid_ratio_lower'] if \ 'humid_ratio_lower' in data else 0 still_air_threshold = data['still_air_threshold'] if \ 'still_air_threshold' in data else 0.1 return cls(ppd_comfort_thresh, humid_ratio_upper, humid_ratio_lower, still_air_threshold)
[docs] @classmethod def from_string(cls, pmv_parameter_string): """Create an PMVParameter object from an PMVParameter string.""" str_pattern = re.compile(r"\-\-(\S*\s\S*)") matches = str_pattern.findall(pmv_parameter_string) par_dict = {item.split(' ')[0]: item.split(' ')[1] for item in matches} ppd_threshold = float(par_dict['ppd-threshold']) \ if 'ppd-threshold' in par_dict else None hr_upper = float(par_dict['hr-upper']) \ if 'hr-upper' in par_dict else None hr_lower = float(par_dict['hr-lower']) \ if 'hr-lower' in par_dict else None still_air_threshold = float(par_dict['still-air-threshold']) \ if 'still-air-threshold' in par_dict else None return cls(ppd_threshold, hr_upper, hr_lower, still_air_threshold)
@property def ppd_comfort_thresh(self): """The threshold of the percentage of people dissatisfied (PPD) beyond which the conditions are not acceptable. The default is 10%. """ return self._ppd_thresh @ppd_comfort_thresh.setter def ppd_comfort_thresh(self, ppd): assert 5 <= ppd <= 100, \ 'ppd_comfort_thresh must be between 5 and 100. Got {}'.format(ppd) self._ppd_thresh = ppd @property def humid_ratio_upper(self): """A number representing the upper boundary of humidity ratio above which conditions are considered too humid to be comfortable. The default is set to 0.03 kg wather/kg air. """ return self._hr_upper @property def humid_ratio_lower(self): """A number representing the lower boundary of humidity ratio below which conditions are considered too dry to be comfortable. The default is set to 0 kg wather/kg air. """ return self._hr_lower @property def still_air_threshold(self): """A number representing the wind speed beyond which the formula for Standard Effective Temperature (SET) is used to determine PMV/PPD (as opposed to Fanger's original equation). The default is set to 0.1 m/s. """ return self._still_thresh
[docs] def set_ppd_comfort_thresh_from_comfort_class(self, comfort_class): """Set the PPD threshold given the EN-15251 comfort class.""" self.ppd_comfort_thresh = ppd_threshold_from_comfort_class(comfort_class)
[docs] def is_comfortable(self, ppd, humidity_ratio=0): """Determine if conditions are comfortable or not. Values are one of the following: * 0 = uncomfortable * 1 = comfortable """ return 1 if (ppd <= self._ppd_thresh and humidity_ratio >= self._hr_lower and humidity_ratio <= self._hr_upper) else 0
[docs] def thermal_condition(self, pmv, ppd): """Determine whether conditions are cold, neutral or hot. Values are one of the following: * -1 = cold * 0 = netural * +1 = hot """ if ppd >= self._ppd_thresh: return 1 if pmv > 0 else -1 else: return 0
[docs] def discomfort_reason(self, pmv, ppd, humidity_ratio=0): """Determine the reason why conditions are comfortable or not. Values are one of the following: * -2 = too dry * -1 = too cold * 0 = comfortable * +1 = too hot * +2 = too humid """ if ppd >= self._ppd_thresh: return 1 if pmv > 0 else -1 elif humidity_ratio < self._hr_lower: return -2 elif humidity_ratio > self._hr_upper: return 2 else: return 0
[docs] def to_dict(self): """PMVParameter dictionary representation.""" return { 'type': 'PMVParameter', 'ppd_comfort_thresh': self.ppd_comfort_thresh, 'humid_ratio_upper': self.humid_ratio_upper, 'humid_ratio_lower': self.humid_ratio_lower, 'still_air_threshold': self.still_air_threshold }
def __copy__(self): return PMVParameter(self.ppd_comfort_thresh, self.humid_ratio_upper, self.humid_ratio_lower, self.still_air_threshold) def __repr__(self): """PMV comfort parameters representation.""" return '--ppd-threshold {} --hr-upper {} ' \ '--hr-lower {} --still-air-threshold {}'.format( self._ppd_thresh, self._hr_upper, self._hr_lower, self._still_thresh)