voxcity.simulator_gpu.solar.integration ======================================= .. py:module:: voxcity.simulator_gpu.solar.integration .. autoapi-nested-parse:: VoxCity GPU-accelerated Solar Irradiance Integration Package This package provides GPU-accelerated solar irradiance calculations for VoxCity voxel grids using Taichi. It supports: - Ground-level (horizontal) solar irradiance maps - Building surface irradiance with directional faces - Volumetric 3D radiation fields for thermal comfort analysis - Cumulative time-integrated irradiance and sunlight hours - Sky patch discretization (Tregenza, Reinhart, uniform, Fibonacci) - Surface reflections (optional) Modules: - utils: Common helper functions - caching: Cache infrastructure for models and calculators - ground: Ground-level solar irradiance functions - building: Building surface irradiance functions - volumetric: Volumetric 3D radiation field functions Public API: The package re-exports all public functions for backward compatibility. Import directly from this package: from voxcity.simulator_gpu.solar.integration import ( get_global_solar_irradiance_map, get_cumulative_global_solar_irradiance, get_sunlight_hours, get_building_solar_irradiance, get_volumetric_solar_irradiance_map, # ... etc ) Submodules ---------- .. toctree:: :maxdepth: 1 /autoapi/voxcity/simulator_gpu/solar/integration/building/index /autoapi/voxcity/simulator_gpu/solar/integration/caching/index /autoapi/voxcity/simulator_gpu/solar/integration/ground/index /autoapi/voxcity/simulator_gpu/solar/integration/utils/index /autoapi/voxcity/simulator_gpu/solar/integration/volumetric/index Attributes ---------- .. autoapisummary:: voxcity.simulator_gpu.solar.integration.VOXCITY_GROUND_CODE voxcity.simulator_gpu.solar.integration.VOXCITY_TREE_CODE voxcity.simulator_gpu.solar.integration.VOXCITY_BUILDING_CODE Classes ------- .. toctree:: :hidden: /autoapi/voxcity/simulator_gpu/solar/integration/ArrayWithMetadata .. autoapisummary:: voxcity.simulator_gpu.solar.integration.ArrayWithMetadata Functions --------- .. autoapisummary:: voxcity.simulator_gpu.solar.integration.get_location_from_voxcity voxcity.simulator_gpu.solar.integration.convert_voxel_data_to_arrays voxcity.simulator_gpu.solar.integration.compute_valid_ground_vectorized voxcity.simulator_gpu.solar.integration.compute_sun_direction voxcity.simulator_gpu.solar.integration.parse_time_period voxcity.simulator_gpu.solar.integration.filter_df_to_period voxcity.simulator_gpu.solar.integration.load_epw_data voxcity.simulator_gpu.solar.integration.get_solar_positions_astral voxcity.simulator_gpu.solar.integration.extract_terrain_following_slice voxcity.simulator_gpu.solar.integration.accumulate_terrain_following_slice voxcity.simulator_gpu.solar.integration.compute_boundary_vertical_mask voxcity.simulator_gpu.solar.integration.apply_computation_mask_to_faces Package Contents ---------------- .. py:function:: get_location_from_voxcity(voxcity, default_lat: float = 1.35, default_lon: float = 103.82) -> Tuple[float, float] Extract latitude/longitude from VoxCity object or return defaults. :param voxcity: VoxCity object with extras containing rectangle_vertices :param default_lat: Default latitude if not found (Singapore) :param default_lon: Default longitude if not found (Singapore) :returns: Tuple of (origin_lat, origin_lon) .. py:function:: convert_voxel_data_to_arrays(voxel_data: numpy.ndarray, default_lad: float = 1.0) -> Tuple[numpy.ndarray, numpy.ndarray] Convert VoxCity voxel codes to is_solid and LAD arrays using vectorized operations. This is 10-100x faster than triple-nested Python loops for large grids. :param voxel_data: 3D array of VoxCity voxel class codes :param default_lad: Default Leaf Area Density for tree voxels (m²/m³) :returns: Tuple of (is_solid, lad) numpy arrays with same shape as voxel_data .. py:function:: compute_valid_ground_vectorized(voxel_data: numpy.ndarray) -> Tuple[numpy.ndarray, numpy.ndarray] Compute valid ground mask and ground k-levels using vectorized operations. Valid ground cells are those where: - The transition from solid to air/tree occurs - The solid below is not water (7,8,9) or building/underground (negative codes) :param voxel_data: 3D array of VoxCity voxel class codes (ni, nj, nk) :returns: Tuple of (valid_ground 2D bool array, ground_k 2D int array) ground_k[i,j] = -1 means no valid ground found .. py:function:: compute_sun_direction(azimuth_degrees_ori: float, elevation_degrees: float, rotation_angle: float = 0) -> Tuple[float, float, float, float] Compute sun direction vector from azimuth and elevation angles. :param azimuth_degrees_ori: Solar azimuth in VoxCity convention (0=North, clockwise) :param elevation_degrees: Solar elevation in degrees above horizon :param rotation_angle: Grid rotation angle in degrees (clockwise, from voxcity.extras) :returns: Tuple of (sun_dir_x, sun_dir_y, sun_dir_z, cos_zenith) .. py:function:: parse_time_period(start_time: str, end_time: str) -> Tuple[datetime.datetime, datetime.datetime] Parse start and end time strings. :param start_time: Start time in format 'MM-DD HH:MM:SS' :param end_time: End time in format 'MM-DD HH:MM:SS' :returns: Tuple of (start_dt, end_dt) datetime objects :raises ValueError: If time format is invalid .. py:function:: filter_df_to_period(df, start_time: str, end_time: str, tz: float) Filter weather DataFrame to specified time period and convert to UTC. :param df: pandas DataFrame with datetime index :param start_time: Start time in format 'MM-DD HH:MM:SS' :param end_time: End time in format 'MM-DD HH:MM:SS' :param tz: Timezone offset in hours :returns: Tuple of (df_period_utc, df with hour_of_year column) :raises ValueError: If time format is invalid or no data in period .. py:function:: load_epw_data(epw_file_path: Optional[str] = None, download_nearest_epw: bool = False, voxcity=None, **kwargs) -> Tuple Load EPW weather data, optionally downloading the nearest file. :param epw_file_path: Path to EPW file (required if download_nearest_epw=False) :param download_nearest_epw: If True, download nearest EPW based on location :param voxcity: VoxCity object (needed for location when downloading) :param \*\*kwargs: Additional parameters (output_dir, max_distance, rectangle_vertices) :returns: Tuple of (df, lon, lat, tz) where df is the weather DataFrame :raises ValueError: If EPW file not provided and download_nearest_epw=False :raises ImportError: If required modules not available .. py:function:: get_solar_positions_astral(times, lon: float, lat: float) Compute solar azimuth and elevation for given times and location using Astral. :param times: Pandas DatetimeIndex of times (should be timezone-aware, preferably UTC) :param lon: Longitude in degrees :param lat: Latitude in degrees :returns: DataFrame indexed by times with columns ['azimuth', 'elevation'] in degrees .. py:function:: extract_terrain_following_slice(flux_3d: numpy.ndarray, ground_k: numpy.ndarray, height_offset_k: int, is_solid: numpy.ndarray) -> numpy.ndarray Extract a terrain-following 2D slice from a 3D flux field (vectorized). For each (i,j), extracts the value at ground_k[i,j] + height_offset_k. Cells that are solid at the extraction point, have no valid ground, or are above the domain are marked as NaN. :param flux_3d: 3D array of flux values (ni, nj, nk) :param ground_k: 2D array of ground k-levels (ni, nj), -1 means no valid ground :param height_offset_k: Number of cells above ground to extract :param is_solid: 3D array marking solid cells (ni, nj, nk) :returns: 2D array of extracted values (ni, nj) with NaN for invalid cells .. py:function:: accumulate_terrain_following_slice(cumulative_map: numpy.ndarray, flux_3d: numpy.ndarray, ground_k: numpy.ndarray, height_offset_k: int, is_solid: numpy.ndarray, weight: float = 1.0) -> None Accumulate terrain-following values from a 3D flux field into a 2D map (vectorized, in-place). For each (i,j), adds flux_3d[i,j,k_extract] * weight to cumulative_map[i,j] where k_extract = ground_k[i,j] + height_offset_k. :param cumulative_map: 2D array to accumulate into (ni, nj), modified in-place :param flux_3d: 3D array of flux values (ni, nj, nk) :param ground_k: 2D array of ground k-levels (ni, nj), -1 means no valid ground :param height_offset_k: Number of cells above ground to extract :param is_solid: 3D array marking solid cells (ni, nj, nk) :param weight: Multiplier for values before accumulating (e.g., time_step_hours) .. py:function:: compute_boundary_vertical_mask(mesh_face_centers: numpy.ndarray, mesh_face_normals: numpy.ndarray, grid_bounds: numpy.ndarray, boundary_epsilon: float) -> numpy.ndarray Compute mask for vertical faces on domain boundary. :param mesh_face_centers: (N, 3) array of face center coordinates :param mesh_face_normals: (N, 3) array of face normal vectors :param grid_bounds: (2, 3) array of [[min_x, min_y, min_z], [max_x, max_y, max_z]] :param boundary_epsilon: Tolerance for boundary detection :returns: Boolean mask (N,) - True for vertical boundary faces .. py:function:: apply_computation_mask_to_faces(values: numpy.ndarray, mesh_face_centers: numpy.ndarray, computation_mask: numpy.ndarray, meshsize: float, grid_shape: Tuple[int, int]) -> numpy.ndarray Apply 2D computation mask to mesh face values. :param values: (N,) array of face values :param mesh_face_centers: (N, 3) array of face center coordinates :param computation_mask: 2D boolean mask matching grid_shape :param meshsize: Grid cell size :param grid_shape: (ny_vc, nx_vc) grid dimensions :returns: Modified values array with NaN for masked-out faces .. py:data:: VOXCITY_GROUND_CODE :value: -1 .. py:data:: VOXCITY_TREE_CODE :value: -2 .. py:data:: VOXCITY_BUILDING_CODE :value: -3