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'
        }]
Example #3
0
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
Example #4
0
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'}
        ]