class PointInTimeGridRayTracing(DAG): """Point-in-time grid-based ray tracing.""" # inputs sensor_count = Inputs.int( default=200, description='The maximum number of grid points per parallel execution', spec={ 'type': 'integer', 'minimum': 1 }) radiance_parameters = Inputs.str( description='The radiance parameters for ray tracing', default='-ab 2 -aa 0.1 -ad 2048 -ar 64') metric = Inputs.str( description= 'Text for the type of metric to be output from the calculation. ' 'Choose from: illuminance, irradiance, luminance, radiance.', default='illuminance', spec={ 'type': 'string', 'enum': ['illuminance', 'irradiance', 'luminance', 'radiance'] }) octree_file = Inputs.file(description='A Radiance octree file.', extensions=['oct']) grid_name = Inputs.str( description= 'Sensor grid file name. This is useful to rename the final result ' 'file to {grid_name}.res') sensor_grid = Inputs.file(description='Sensor grid file.', extensions=['pts']) bsdfs = Inputs.folder( description='Folder containing any BSDF files needed for ray tracing.') @task(template=SplitGrid) def split_grid(self, sensor_count=sensor_count, input_grid=sensor_grid): return [{ 'from': SplitGrid()._outputs.grids_list }, { 'from': SplitGrid()._outputs.output_folder, 'to': 'sub_grids' }] @task(template=RayTracingPointInTime, needs=[split_grid], loop=split_grid._outputs.grids_list, sub_folder='results', sub_paths={'grid': '{{item.path}}'}) def ray_tracing(self, radiance_parameters=radiance_parameters, metric=metric, grid=split_grid._outputs.output_folder, scene_file=octree_file, bsdf_folder=bsdfs): return [{ 'from': RayTracingPointInTime()._outputs.result, 'to': '{{item.name}}.res' }] @task(template=MergeFiles, needs=[ray_tracing]) def merge_results(self, name=grid_name, extension='.res', folder='results'): return [{ 'from': MergeFiles()._outputs.result_file, 'to': '../../results/{{self.name}}.res' }]
class AnnualDaylightRayTracing(DAG): # inputs radiance_parameters = Inputs.str( description='The radiance parameters for ray tracing', default='-ab 2 -ad 5000 -lw 2e-05') octree_file_with_suns = Inputs.file( description='A Radiance octree file with suns.', extensions=['oct']) octree_file = Inputs.file(description='A Radiance octree file.', extensions=['oct']) grid_name = Inputs.str( description= 'Sensor grid file name. This is useful to rename the final result ' 'file to {grid_name}.ill') sensor_grid = Inputs.file(description='Sensor grid file.', extensions=['pts']) sensor_count = Inputs.int( description='Number of sensors in the input sensor grid.') sun_modifiers = Inputs.file(description='A file with sun modifiers.') sky_matrix = Inputs.file(description='Path to total sky matrix file.') sky_matrix_direct = Inputs.file( description='Path to direct skymtx file (i.e. gendaymtx -d).') sky_dome = Inputs.file(description='Path to sky dome file.') bsdfs = Inputs.folder( description='Folder containing any BSDF files needed for ray tracing.', optional=True) @task(template=DaylightContribution) def direct_sunlight( self, name=grid_name, radiance_parameters=radiance_parameters, fixed_radiance_parameters='-aa 0.0 -I -ab 0 -dc 1.0 -dt 0.0 -dj 0.0 -dr 0', sensor_count=sensor_count, modifiers=sun_modifiers, sensor_grid=sensor_grid, output_format='a', # make it ascii so we expose the file as a separate output scene_file=octree_file_with_suns, bsdf_folder=bsdfs): return [{ 'from': DaylightContribution()._outputs.result_file, 'to': '../final/direct/{{self.name}}.ill' }] @task(template=DaylightCoefficient) def direct_sky(self, radiance_parameters=radiance_parameters, fixed_radiance_parameters='-aa 0.0 -I -ab 1 -c 1 -faf', sensor_count=sensor_count, sky_matrix=sky_matrix_direct, sky_dome=sky_dome, sensor_grid=sensor_grid, scene_file=octree_file, bsdf_folder=bsdfs): return [{ 'from': DaylightCoefficient()._outputs.result_file, 'to': 'direct_sky.ill' }] @task(template=DaylightCoefficient) def total_sky(self, radiance_parameters=radiance_parameters, fixed_radiance_parameters='-aa 0.0 -I -c 1 -faf', sensor_count=sensor_count, sky_matrix=sky_matrix, sky_dome=sky_dome, sensor_grid=sensor_grid, scene_file=octree_file, bsdf_folder=bsdfs): return [{ 'from': DaylightCoefficient()._outputs.result_file, 'to': 'total_sky.ill' }] @task(template=AddRemoveSkyMatrix, needs=[direct_sunlight, total_sky, direct_sky]) def output_matrix_math( self, name=grid_name, direct_sky_matrix=direct_sky._outputs.result_file, total_sky_matrix=total_sky._outputs.result_file, sunlight_matrix=direct_sunlight._outputs.result_file, conversion='47.4 119.9 11.6'): return [{ 'from': AddRemoveSkyMatrix()._outputs.results_file, 'to': '../final/total/{{self.name}}.ill' }]
class DynamicShadeContribEntryPoint(DAG): """Entry point for computing the contributions from dynamic windows.""" # inputs radiance_parameters = Inputs.str( description='Radiance parameters for ray tracing.', default='-ab 2 -ad 5000 -lw 2e-05', ) octree_file = Inputs.file( description= 'A Radiance octree file with a completely transparent version ' 'of the dynamic shade group.', extensions=['oct']) octree_file_with_suns = Inputs.file( description='A Radiance octree file with sun modifiers.', extensions=['oct']) group_name = Inputs.str( description='Name for the dynamic aperture group being simulated.') sensor_grid_folder = Inputs.folder( description= 'A folder containing all of the split sensor grids in the model.') sensor_grids = Inputs.file( description= 'A JSON file with information about sensor grids to loop over.') sky_dome = Inputs.file(description='Path to sky dome file.') sky_matrix = Inputs.file(description='Path to total sky matrix file.') sky_matrix_direct = Inputs.file( description='Path to direct skymtx file (gendaymtx -d).') sun_modifiers = Inputs.file(description='A file with sun modifiers.') sun_up_hours = Inputs.file( description= 'A sun-up-hours.txt file output by Radiance and aligns with the ' 'input irradiance files.') @task(template=ReadJSONList) def read_grids_for_shade(self, src=sensor_grids) -> List[Dict]: return [{ 'from': ReadJSONList()._outputs.data, 'description': 'Sensor grids information.' }] @task(template=ShadeContribEntryPoint, needs=[read_grids_for_shade], loop=read_grids_for_shade._outputs.data, sub_folder='shortwave', sub_paths={ 'sensor_grid': '{{item.full_id}}.pts', 'ref_sensor_grid': '{{item.full_id}}_ref.pts', }) def run_radiance_shade_contrib(self, radiance_parameters=radiance_parameters, octree_file=octree_file, octree_file_with_suns=octree_file_with_suns, group_name=group_name, grid_name='{{item.full_id}}', sensor_grid=sensor_grid_folder, ref_sensor_grid=sensor_grid_folder, sensor_count='{{item.count}}', sky_dome=sky_dome, sky_matrix=sky_matrix, sky_matrix_direct=sky_matrix_direct, sun_modifiers=sun_modifiers, sun_up_hours=sun_up_hours) -> List[Dict]: pass
class ComfortMappingEntryPoint(DAG): """Entry point for Comfort calculations.""" # inputs epw = Inputs.file( description='Weather file used for the comfort map.', extensions=['epw'] ) result_sql = Inputs.file( description='A SQLite file that was generated by EnergyPlus and contains ' 'hourly or sub-hourly thermal comfort results.', extensions=['sql', 'db', 'sqlite'] ) grid_name = Inputs.str( description='Sensor grid file name (used to name the final result files).' ) enclosure_info = Inputs.file( description='A JSON file containing information about the radiant ' 'enclosure that sensor points belong to.', extensions=['json'] ) view_factors = Inputs.file( description='A CSV of spherical view factors to the surfaces in the result-sql.', extensions=['csv'] ) modifiers = Inputs.file( description='Path to a modifiers file that aligns with the view-factors.', extensions=['mod', 'txt'] ) indirect_irradiance = Inputs.file( description='An .ill containing the indirect irradiance for each sensor.', extensions=['ill', 'irr'] ) direct_irradiance = Inputs.file( description='An .ill containing direct irradiance for each sensor.', extensions=['ill', 'irr'] ) ref_irradiance = Inputs.file( description='An .ill containing ground-reflected irradiance for each ' 'sensor.', extensions=['ill', 'irr'] ) sun_up_hours = Inputs.file( description='A sun-up-hours.txt file output by Radiance and aligns with the ' 'input irradiance files.' ) contributions = Inputs.folder( description='An optional folder containing sub-folders of irradiance ' 'contributions from dynamic aperture groups. There should be one sub-folder ' 'per window group and each one should contain three .ill files named ' 'direct.ill, indirect.ill and reflected.ill. If specified, these will be ' 'added to the irradiance inputs before computing shortwave MRT deltas.', optional=True ) transmittance_contribs = Inputs.folder( description='An optional folder containing a transmittance schedule JSON ' 'and sub-folders of irradiance results that exclude the shade from the ' 'calculation. There should be one sub-folder per window groups and each ' 'one should contain three .ill files named direct.ill, indirect.ill and ' 'reflected.ill. If specified, these will be added to the irradiance inputs ' 'before computing shortwave MRT deltas.', optional=True ) trans_schedules = Inputs.file( description='A schedule JSON that contains fractional schedule values ' 'for each shade transmittance schedule in the model.' ) occ_schedules = Inputs.file( description='A JSON file containing occupancy schedules derived from ' 'the input model.' ) run_period = Inputs.str( description='An AnalysisPeriod string to set the start and end dates of ' 'the simulation (eg. "6/21 to 9/21 between 0 and 23 @1"). If None, ' 'the simulation will be annual.', default='' ) air_speed = Inputs.file( description='A CSV file containing a single number for air speed in m/s or ' 'several rows of air speeds that align with the length of the run period.', optional=True ) met_rate = Inputs.file( description='A CSV file containing a single number for metabolic rate in met ' 'or several rows of met values that align with the length of the run period.', optional=True ) clo_value = Inputs.file( description='A CSV file containing a single number for clothing level in clo ' 'or several rows of clo values that align with the length of the run period.', optional=True ) solarcal_parameters = Inputs.str( description='A SolarCalParameter string to customize the assumptions of ' 'the SolarCal model.', default='--posture seated --sharp 135 ' '--absorptivity 0.7 --emissivity 0.95' ) comfort_parameters = Inputs.str( description='An PMVParameter string to customize the assumptions of ' 'the PMV comfort model.', default='--ppd-threshold 10' ) write_set_map = Inputs.str( description='A switch to note whether the output temperature CSV should ' 'record Operative Temperature or Standard Effective Temperature (SET).', default='write-op-map' ) @task(template=LongwaveMrtMap) def create_longwave_mrt_map( self, result_sql=result_sql, view_factors=view_factors, modifiers=modifiers, enclosure_info=enclosure_info, epw=epw, run_period=run_period, name=grid_name ) -> List[Dict]: return [ { 'from': LongwaveMrtMap()._outputs.longwave_mrt_map, 'to': 'conditions/longwave_mrt/{{self.name}}.csv' } ] @task(template=ShortwaveMrtMap) def create_shortwave_mrt_map( self, epw=epw, indirect_irradiance=indirect_irradiance, direct_irradiance=direct_irradiance, ref_irradiance=ref_irradiance, sun_up_hours=sun_up_hours, contributions=contributions, transmittance_contribs=transmittance_contribs, trans_schedules=trans_schedules, solarcal_par=solarcal_parameters, run_period=run_period, name=grid_name ) -> List[Dict]: return [ { 'from': ShortwaveMrtMap()._outputs.shortwave_mrt_map, 'to': 'conditions/shortwave_mrt/{{self.name}}.csv' } ] @task(template=AirMap) def create_air_temperature_map( self, result_sql=result_sql, enclosure_info=enclosure_info, epw=epw, run_period=run_period, metric='air-temperature', name=grid_name ) -> List[Dict]: return [ { 'from': AirMap()._outputs.air_map, 'to': 'conditions/air_temperature/{{self.name}}.csv' } ] @task(template=AirMap) def create_rel_humidity_map( self, result_sql=result_sql, enclosure_info=enclosure_info, epw=epw, run_period=run_period, metric='relative-humidity', name=grid_name ) -> List[Dict]: return [ { 'from': AirMap()._outputs.air_map, 'to': 'conditions/rel_humidity/{{self.name}}.csv' } ] @task(template=AirSpeedJson) def create_air_speed_json( self, epw=epw, enclosure_info=enclosure_info, multiply_by=0.5, indoor_air_speed=air_speed, run_period=run_period, name=grid_name ) -> List[Dict]: return [ { 'from': AirSpeedJson()._outputs.air_speeds, 'to': 'conditions/air_speed/{{self.name}}.json' } ] @task( template=PmvMtx, needs=[ create_longwave_mrt_map, create_shortwave_mrt_map, create_air_temperature_map, create_rel_humidity_map, create_air_speed_json ] ) def process_pmv_matrix( self, air_temperature_mtx=create_air_temperature_map._outputs.air_map, rel_humidity_mtx=create_rel_humidity_map._outputs.air_map, rad_temperature_mtx=create_longwave_mrt_map._outputs.longwave_mrt_map, rad_delta_mtx=create_shortwave_mrt_map._outputs.shortwave_mrt_map, air_speed_json=create_air_speed_json._outputs.air_speeds, met_rate=met_rate, clo_value=clo_value, comfort_par=comfort_parameters, write_set_map=write_set_map, name=grid_name ) -> List[Dict]: return [ { 'from': PmvMtx()._outputs.temperature_map, 'to': 'results/temperature/{{self.name}}.csv' }, { 'from': PmvMtx()._outputs.condition_map, 'to': 'results/condition/{{self.name}}.csv' }, { 'from': PmvMtx()._outputs.pmv_map, 'to': 'results/condition_intensity/{{self.name}}.csv' } ] @task( template=Tcp, needs=[process_pmv_matrix] ) def compute_tcp( self, condition_csv=process_pmv_matrix._outputs.condition_map, enclosure_info=enclosure_info, occ_schedule_json=occ_schedules, name=grid_name ) -> List[Dict]: return [ {'from': Tcp()._outputs.tcp, 'to': 'metrics/TCP/{{self.name}}.csv'}, {'from': Tcp()._outputs.hsp, 'to': 'metrics/HSP/{{self.name}}.csv'}, {'from': Tcp()._outputs.csp, 'to': 'metrics/CSP/{{self.name}}.csv'} ]