From 154b41aa3b8c4d02b9978bc1ab56a3571a9d7b73 Mon Sep 17 00:00:00 2001 From: Chris Mackey Date: Mon, 1 Mar 2021 15:53:54 -0500 Subject: [PATCH] feat(recipe): Add outputs for Thermal Comfort Percent --- pollination/pmv_comfort_map/entry.py | 104 ++++++++++++++++++++++++--- requirements.txt | 4 +- 2 files changed, 96 insertions(+), 12 deletions(-) diff --git a/pollination/pmv_comfort_map/entry.py b/pollination/pmv_comfort_map/entry.py index 61e0c83..1284970 100644 --- a/pollination/pmv_comfort_map/entry.py +++ b/pollination/pmv_comfort_map/entry.py @@ -4,11 +4,12 @@ # pollination plugins and recipes from pollination.ladybug.translate import EpwToWea -from pollination.ladybug_comfort.map import PmvMap, MapResultInfo +from pollination.ladybug_comfort.map import PmvMap, MapResultInfo, Tcp from pollination.honeybee_radiance.translate import CreateRadiantEnclosureInfo from pollination.honeybee_radiance.edit import MirrorModelSensorGrids from pollination.honeybee_energy.settings import SimParComfort from pollination.honeybee_energy.simulate import SimulateModel +from pollination.honeybee_energy.translate import ModelOccSchedules from pollination.lbt_honeybee.edit import ModelModifiersFromConstructions from pollination.annual_radiation.entry import AnnualRadiationEntryPoint @@ -18,6 +19,7 @@ from pollination.alias.inputs.data import value_or_data from pollination.alias.inputs.north import north_input from pollination.alias.inputs.bool_options import write_set_map_input +from pollination.alias.outputs.comfort import comfort_percent_output @dataclass @@ -141,7 +143,27 @@ def get_enclosure_info(self, model=model) -> List[Dict]: }, { 'from': CreateRadiantEnclosureInfo()._outputs.enclosure_list_file, - 'to': 'results/grids_info.json' + 'to': 'results/temperature/grids_info.json' + }, + { + 'from': CreateRadiantEnclosureInfo()._outputs.enclosure_list_file, + 'to': 'results/condition/grids_info.json' + }, + { + 'from': CreateRadiantEnclosureInfo()._outputs.enclosure_list_file, + 'to': 'results/condition_intensity/grids_info.json' + }, + { + 'from': CreateRadiantEnclosureInfo()._outputs.enclosure_list_file, + 'to': 'metrics/TCP/grids_info.json' + }, + { + 'from': CreateRadiantEnclosureInfo()._outputs.enclosure_list_file, + 'to': 'metrics/HSP/grids_info.json' + }, + { + 'from': CreateRadiantEnclosureInfo()._outputs.enclosure_list_file, + 'to': 'metrics/CSP/grids_info.json' }, { 'from': CreateRadiantEnclosureInfo()._outputs.enclosure_list, @@ -184,10 +206,10 @@ def run_irradiance_simulation( loop=get_enclosure_info._outputs.enclosure_list, sub_folder='results', # create a subfolder for each grid sub_paths={ - 'enclosure_info': '{{item.id}}.json', # sub_path for enclosure_info arg - 'total_irradiance': '{{item.id}}.ill', # sub_path for total irradiance arg - 'direct_irradiance': '{{item.id}}.ill', # sub_path for total direct_irradiance arg - 'ref_irradiance': '{{item.id}}_ref.ill', # sub_path for reflected irradiance arg + 'enclosure_info': '{{item.id}}.json', + 'total_irradiance': '{{item.id}}.ill', + 'direct_irradiance': '{{item.id}}.ill', + 'ref_irradiance': '{{item.id}}_ref.ill', 'sun_up_hours': 'sun-up-hours.txt' } ) @@ -222,8 +244,48 @@ def create_result_info( self, comfort_model='pmv', run_period=run_period, qualifier=write_set_map ) -> List[Dict]: return [ - {'from': MapResultInfo()._outputs.results_info_file, - 'to': 'results/results_info.json'} + { + 'from': MapResultInfo()._outputs.temperature_info, + 'to': 'results/temperature/results_info.json' + }, + { + 'from': MapResultInfo()._outputs.condition_info, + 'to': 'results/condition/results_info.json' + }, + { + 'from': MapResultInfo()._outputs.condition_intensity_info, + 'to': 'results/condition_intensity/results_info.json' + } + ] + + @task(template=ModelOccSchedules) + def create_model_occ_schedules( + self, model=model, period=run_period + ) -> List[Dict]: + return [ + {'from': ModelOccSchedules()._outputs.occ_schedule_json, + 'to': 'metrics/occupancy_schedules.json'} + ] + + @task( + template=Tcp, + needs=[create_model_occ_schedules, get_enclosure_info, run_comfort_map], + loop=get_enclosure_info._outputs.enclosure_list, + sub_folder='metrics', # create a subfolder for the whole simulation + sub_paths={ + 'condition_csv': '{{item.id}}.csv', + 'enclosure_info': '{{item.id}}.json' + } + ) + def compute_tcp( + self, condition_csv='results/condition', + enclosure_info=get_enclosure_info._outputs.output_folder, + occ_schedule_json=create_model_occ_schedules._outputs.occ_schedule_json + ) -> List[Dict]: + return [ + {'from': Tcp()._outputs.tcp, 'to': 'TCP/{{item.id}}.csv'}, + {'from': Tcp()._outputs.hsp, 'to': 'HSP/{{item.id}}.csv'}, + {'from': Tcp()._outputs.csp, 'to': 'CSP/{{item.id}}.csv'} ] # outputs @@ -234,7 +296,9 @@ def create_result_info( temperature = Outputs.folder( source='results/temperature', description='A folder containing CSV maps of ' - 'Operative Temperature for each sensor grid. Values are in Celsius.' + 'Operative Temperature for each sensor grid. Alternatively, if the ' + 'write-set-map option is used, the CSV maps here will contain Standard ' + 'Effective Temperature (SET). Values are in Celsius.' ) condition = Outputs.folder( @@ -244,9 +308,29 @@ def create_result_info( '(comfortable) conditions.' ) - condition_intensity = Outputs.folder( + pmv = Outputs.folder( source='results/condition_intensity', description='A folder containing CSV maps ' 'of the Predicted Mean Vote (PMV) for each sensor grid. This can be used ' 'to understand not just whether conditions are acceptable but how ' 'uncomfortably hot or cold they are.' ) + + tcp = Outputs.folder( + source='metrics/TCP', description='A folder containing CSV values for Thermal ' + 'Comfort Percent (TCP). TCP is the percentage of occupied time where ' + 'thermal conditions are acceptable/comfortable.', alias=comfort_percent_output + ) + + hsp = Outputs.folder( + source='metrics/HSP', description='A folder containing CSV values for Heat ' + 'Sensation Percent (HSP). HSP is the percentage of occupied time where ' + 'thermal conditions are hotter than what is considered acceptable/comfortable.', + alias=comfort_percent_output + ) + + csp = Outputs.folder( + source='metrics/CSP', description='A folder containing CSV values for Cold ' + 'Sensation Percent (CSP). CSP is the percentage of occupied time where ' + 'thermal conditions are colder than what is considered acceptable/comfortable.', + alias=comfort_percent_output + ) diff --git a/requirements.txt b/requirements.txt index ebf6495..d6e33f1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ pollination-ladybug>=0.1.4 -pollination-ladybug-comfort>=0.1.3 +pollination-ladybug-comfort>=0.2.1 pollination-honeybee-radiance>=0.6.2 -pollination-honeybee-energy>=0.2.6 +pollination-honeybee-energy>=0.2.7 pollination-lbt-honeybee>=0.1.0 pollination-annual-radiation>=0.1.1 pollination-alias>=0.2.3