solweig-gpu 1.2.22__tar.gz → 2.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/MANIFEST.in +0 -1
  2. solweig_gpu-2.0.1/PKG-INFO +492 -0
  3. solweig_gpu-2.0.1/README.md +449 -0
  4. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/setup.py +1 -3
  5. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_gpu/__init__.py +10 -2
  6. solweig_gpu-2.0.1/solweig_gpu/calculate_wbgt.py +761 -0
  7. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_gpu/cli.py +36 -12
  8. solweig_gpu-2.0.1/solweig_gpu/create_inputs.py +1851 -0
  9. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_gpu/landcoverclasses_2016a.txt +1 -1
  10. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_gpu/preprocessor.py +1526 -983
  11. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_gpu/shadow.py +253 -40
  12. solweig_gpu-2.0.1/solweig_gpu/solweig_gpu.py +685 -0
  13. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_gpu/sun_position.py +11 -8
  14. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_gpu/utci_process.py +381 -21
  15. solweig_gpu-2.0.1/solweig_gpu/wind_ext_coeff.py +1049 -0
  16. solweig_gpu-2.0.1/solweig_gpu.egg-info/PKG-INFO +492 -0
  17. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_gpu.egg-info/SOURCES.txt +6 -2
  18. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_gpu.egg-info/entry_points.txt +0 -1
  19. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_gpu.egg-info/requires.txt +0 -1
  20. solweig_gpu-2.0.1/tests/test_create_inputs_austin.py +169 -0
  21. solweig_gpu-2.0.1/tests/test_shadow.py +74 -0
  22. solweig_gpu-1.2.22/tests/test_wrf_and_gui.py → solweig_gpu-2.0.1/tests/test_wrf.py +0 -16
  23. solweig_gpu-1.2.22/PKG-INFO +0 -379
  24. solweig_gpu-1.2.22/README.md +0 -335
  25. solweig_gpu-1.2.22/solweig_gpu/solweig_gpu.py +0 -198
  26. solweig_gpu-1.2.22/solweig_gpu/solweig_gpu_gui.py +0 -476
  27. solweig_gpu-1.2.22/solweig_gpu.egg-info/PKG-INFO +0 -379
  28. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/LICENSE +0 -0
  29. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/Logo.png +0 -0
  30. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/UTCI_New_Delhi.jpeg +0 -0
  31. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/pyproject.toml +0 -0
  32. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/requirements.txt +0 -0
  33. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/setup.cfg +0 -0
  34. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_diagram.png +0 -0
  35. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_gpu/Tgmaps_v1.py +0 -0
  36. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_gpu/calculate_utci.py +0 -0
  37. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_gpu/solweig.py +0 -0
  38. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_gpu/walls_aspect.py +0 -0
  39. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_gpu.egg-info/dependency_links.txt +0 -0
  40. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/solweig_gpu.egg-info/top_level.txt +0 -0
  41. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/tests/__init__.py +0 -0
  42. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/tests/conftest.py +0 -0
  43. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/tests/test_calculate_utci.py +0 -0
  44. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/tests/test_cli.py +0 -0
  45. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/tests/test_era5_processing.py +0 -0
  46. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/tests/test_gpu_smoke.py +0 -0
  47. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/tests/test_integration.py +0 -0
  48. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/tests/test_integration_end_to_end.py +0 -0
  49. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/tests/test_preprocessor.py +0 -0
  50. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/tests/test_sun_position.py +0 -0
  51. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/tests/test_tiling_and_metfiles.py +0 -0
  52. {solweig_gpu-1.2.22 → solweig_gpu-2.0.1}/tests/test_walls_aspect.py +0 -0
@@ -3,7 +3,6 @@ include README.md
3
3
  include LICENSE.rst
4
4
  include requirements.txt
5
5
  recursive-include solweig_gpu *.py
6
- include GUI.png
7
6
  include solweig_diagram.png
8
7
  include Logo.png
9
8
  include UTCI_New_Delhi.jpeg
@@ -0,0 +1,492 @@
1
+ Metadata-Version: 2.4
2
+ Name: solweig-gpu
3
+ Version: 2.0.1
4
+ Summary: GPU-accelerated SOLWEIG model for urban thermal comfort simulation
5
+ Home-page: https://github.com/nvnsudharsan/SOLWEIG-GPU
6
+ Author: Harsh Kamath, Naveen Sudharsan
7
+ Author-email: harsh.kamath@utexas.edu, naveens@utexas.edu
8
+ License: GPL-3.0-only
9
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Operating System :: POSIX :: Linux
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: torch
18
+ Requires-Dist: numpy
19
+ Requires-Dist: scipy
20
+ Requires-Dist: pandas
21
+ Requires-Dist: netCDF4
22
+ Requires-Dist: pytz
23
+ Requires-Dist: shapely
24
+ Requires-Dist: timezonefinder
25
+ Requires-Dist: xarray
26
+ Requires-Dist: tqdm
27
+ Requires-Dist: matplotlib
28
+ Provides-Extra: test
29
+ Requires-Dist: pytest; extra == "test"
30
+ Requires-Dist: pytest-cov; extra == "test"
31
+ Dynamic: author
32
+ Dynamic: author-email
33
+ Dynamic: classifier
34
+ Dynamic: description
35
+ Dynamic: description-content-type
36
+ Dynamic: home-page
37
+ Dynamic: license
38
+ Dynamic: license-file
39
+ Dynamic: provides-extra
40
+ Dynamic: requires-dist
41
+ Dynamic: requires-python
42
+ Dynamic: summary
43
+
44
+ # SOLWEIG-GPU: GPU-Accelerated Thermal Comfort Modeling Framework
45
+
46
+
47
+ <p align="center">
48
+ <img src="https://raw.githubusercontent.com/nvnsudharsan/solweig-gpu/main/Logo_solweig.jpg" alt="SOLWEIG Logo" width="400"/>
49
+ </p>
50
+
51
+ <p align="center">
52
+ <a href="https://www.repostatus.org/#active"><img src="https://img.shields.io/badge/Status-Active-%232ecc71.svg" alt="Project Status: Active"></a>
53
+ <a href="https://pypi.org/project/solweig-gpu/"><img src="https://img.shields.io/pypi/v/solweig-gpu.svg?color=%230d6efd" alt="PyPI version"></a>
54
+ <a href="https://solweig-gpu.readthedocs.io/en/latest/?badge=latest"><img src="https://img.shields.io/badge/docs-latest-%235bc0ff.svg" alt="Documentation Status"></a>
55
+ <a href="https://doi.org/10.5281/zenodo.21081622"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.21081622.svg" alt="DOI"></a>
56
+ <a href="https://www.gnu.org/licenses/gpl-3.0"><img src="https://img.shields.io/badge/License-GPLv3-%230ab5b3.svg" alt="License: GPL v3"></a>
57
+ <a href="https://pepy.tech/projects/solweig-gpu"><img src="https://static.pepy.tech/personalized-badge/solweig-gpu?period=total&units=INTERNATIONAL_SYSTEM&left_color=GRAY&right_color=GREEN&left_text=downloads" alt="PyPI Downloads"></a>
58
+ <a href="https://joss.theoj.org/papers/27faa2bf5f6058d981df8b565f8e9a34"><img src="https://joss.theoj.org/papers/27faa2bf5f6058d981df8b565f8e9a34/status.svg"></a>
59
+ <a href="https://doi.org/10.5194/gmd-19-7389-2026"><img src="https://img.shields.io/badge/DOI-10.5194%2Fgmd--19--7389--2026-blue" alt="GMD"></a>
60
+ <a href="https://github.com/nvnsudharsan/solweig-gpu/actions/workflows/tests.yml"><img src="https://img.shields.io/badge/Tests-Passing-%23ffb703.svg" alt="Tests"></a>
61
+ </p>
62
+
63
+
64
+ **SOLWEIG-GPU** is a Python package and command-line interface for running the standalone SOLWEIG (Solar and LongWave Environmental Irradiance Geometry) model on CPU or GPU (if available). It enables high-resolution urban microclimate modeling by computing key variables such as Sky View Factor (SVF), Mean Radiant Temperature (Tmrt), and the Universal Thermal Climate Index (UTCI).
65
+
66
+ ## What is new in Version 2
67
+
68
+ - Modular code to calculate wall and aspect, sky-view factor, and TMRT/UTCI
69
+ - Ability to compute wet bulb globe temperature (WBGT)
70
+ - Bug fixes
71
+ - Implements GLIDE-SOL (Zonato et al., 2026) features:
72
+ - Download and process the required input datasets
73
+ - Wind direction based wind-extension coefficient calculation (requires ERA5 data)
74
+ - Compute diagnostic urban heat island intensity (UHII) when ERA5 forcing data is used
75
+
76
+ **Cite this work as**
77
+
78
+ 1. Kamath, H. G., Sudharsan, N., Singh, M., Wallenberg, N., Lindberg, F., & Niyogi, D. (2026). SOLWEIG-GPU: GPU-Accelerated Thermal Comfort Modeling Framework for Urban Digital Twins. Journal of Open Source Software, 11(118), 9535. https://doi.org/10.21105/joss.09535
79
+
80
+ 2. Zonato, A., Kamath, H. G., Sudharsan, N., Monaco, L., Kittner, J., Wolf, L., Demuzere, M., Middel, A., Bechtel, B., and Milelli, M.: GLIDE-SOL: a GPU-accelerated global lightweight infrastructure for diagnostic environmental modeling with SOLWEIG, Geosci. Model Dev., 19, 7389–7413, https://doi.org/10.5194/gmd-19-7389-2026, 2026.
81
+
82
+ **SOLWEIG** was originally developed by Dr. Fredrik Lindberg's group. Journal reference: Lindberg, F., Holmer, B. & Thorsson, S. SOLWEIG 1.0 – Modelling spatial variations of 3D radiant fluxes and mean radiant temperature in complex urban settings. *Int J Biometeorol* 52, 697–713 (2008). https://doi.org/10.1007/s00484-008-0162-7
83
+
84
+ **SOLWEIG GPU** code is an extension of the original **SOLWEIG** Python model that is part of the Urban Multi-scale Environmental Predictor (UMEP). GitHub code: https://github.com/UMEP-dev/UMEP
85
+ UMEP journal reference: Lindberg, F., Grimmond, C.S.B., Gabey, A., Huang, B., Kent, C.W., Sun, T., Theeuwes, N.E., Järvi, L., Ward, H.C., Capel-Timms, I. and Chang, Y., 2018. Urban Multi-scale Environmental Predictor (UMEP): An integrated tool for city-based climate services. *Environmental Modelling & Software*, 99, pp.70-87. https://doi.org/10.1016/j.envsoft.2017.09.020
86
+
87
+ ---
88
+
89
+ For detailed documentation, see [Solweig-GPU Documentation](https://solweig-gpu.readthedocs.io/en/latest/index.html)
90
+
91
+ ## Features
92
+
93
+ - CPU and GPU support (automatically uses GPU if available)
94
+ - Divides larger areas into tiles based on the selected tile size
95
+ - CPU-based computations of wall height and aspect are parallelized across multiple CPUs
96
+ - GPU-based computation of SVF, shortwave/longwave radiation, shadows, Tmrt, and UTCI
97
+ - Compatible with meteorological data from UMEP, ERA5, and WRF (`wrfout`)
98
+ - Pipeline can be run in stages (`preprocess`, `run_walls_aspect`, `run_utci_tiles`) for subset-of-tiles or reuse; see [documentation](https://solweig-gpu.readthedocs.io/en/latest/) (Developer Guide and API Reference)
99
+
100
+ ![SOLWEIG-GPU workflow ](https://raw.githubusercontent.com/nvnsudharsan/solweig-gpu/main/solweig_diagram.png)
101
+ *Flowchart of the SOLWEIG-GPU modeling framework*
102
+
103
+ ---
104
+
105
+ ## Required Input Data
106
+
107
+ - `Building DSM`: Includes both buildings and terrain elevation (e.g., `Building_DSM.tif`)
108
+ - `DEM`: Digital Elevation Model excluding buildings (e.g., `DEM.tif`)
109
+ - `Tree DSM`: Vegetation height data only (e.g., `Trees.tif`)
110
+
111
+ ### Currently tested only for hourly data
112
+ - Meteorological forcing:
113
+ - Custom `.txt` file (from UMEP)
114
+ - ERA5 (both instantaneous and accumulated)
115
+ - WRF output NetCDF (`wrfout`)
116
+
117
+
118
+ ### ERA5 Variables Required
119
+ - 2-meter air temperature
120
+ - 2-meter dew point temperature
121
+ - Surface pressure
122
+ - 10-meter U and V wind components
123
+ - Downwelling shortwave radiation (accumulated)
124
+ - Forecasted surface roughness (if wind extinction coefficients are to be calculated)
125
+
126
+ ---
127
+
128
+ ## Output Details
129
+
130
+ - Output directory: `output_folder/` (under the directory you pass as `base_path`)
131
+ - Structure: One folder per tile (e.g., `0_0/`, `1000_0/`)
132
+ - SVF: Single-band raster
133
+ - Other outputs: Multi-band raster (e.g., 24 bands for hourly results)
134
+
135
+ If you need outputs in a different folder, set `base_path` to that directory and pass **complete paths** for the rasters: `building_dsm_filename`, `dem_filename`, `trees_filename`, and `landcover_filename` (optional).
136
+
137
+ ![UTCI for New Delhi](https://raw.githubusercontent.com/nvnsudharsan/solweig-gpu/main/UTCI_New_Delhi.jpeg)
138
+ *UTCI for New Delhi, India, generated using SOLWEIG-GPU and visualized with ArcGIS Online.*
139
+
140
+ ---
141
+
142
+ ## Installation
143
+
144
+ We recommend using conda environment (please see [documentation](./docs/installation.md))
145
+
146
+ ```bash
147
+ conda create -n solweig python=3.10
148
+ conda activate solweig
149
+ conda install -c conda-forge gdal cudnn pytorch timezonefinder matplotlib #cudnn is required only if you are using nvidia GPU
150
+ pip install solweig-gpu
151
+ #if you have older versions installed
152
+ pip install --upgrade solweig-gpu
153
+
154
+ ```
155
+ ## Testing
156
+
157
+ Run the test suite with:
158
+
159
+ ```bash
160
+ pytest -q
161
+ ```
162
+
163
+ With coverage:
164
+
165
+ ```bash
166
+ pytest --cov=solweig_gpu --cov-report=term-missing
167
+ ```
168
+
169
+ CI runs tests on Linux and macOS across Python 3.10–3.12.
170
+
171
+
172
+ ---
173
+
174
+ ## Sample Data
175
+
176
+ Please refer to the sample dataset to familiarize yourself with the expected inputs. Sample data can be found at: <a href="https://doi.org/10.5281/zenodo.21081622"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.21081622.svg" alt="DOI"></a>
177
+
178
+ ---
179
+
180
+ ## Python Usage
181
+
182
+ ### Notes on sample data and forcing options
183
+
184
+ - The `Input_raster` folder in the sample contains the raster files required by SOLWEIG-GPU:
185
+ 1. `Building_DSM.tif`
186
+ 2. `DEM.tif`
187
+ 3. `Trees.tif`
188
+ 4. `Landcover.tif` *(optional)*
189
+
190
+ - SOLWEIG-GPU can be meteorologically forced in three ways:
191
+ 1. Using your own meteorological `.txt` file
192
+ 2. ERA5 reanalysis
193
+ 3. Weather Research and Forecasting (WRF) output files. **Make sure filenames follow one of:**
194
+ - `wrfout_d0x_yyyy-mm-dd_hh_mm_ss` *(preferred; works across operating systems)*
195
+ - `wrfout_d0x_yyyy-mm-dd_hh:mm:ss`
196
+ - `wrfout_d0x_yyyy-mm-dd_hh`
197
+
198
+ - The `Forcing_data` folder in the sample data contains example data for all forcing methods.
199
+
200
+ ---
201
+
202
+ ### Examples
203
+
204
+ #### Data download (optional)
205
+
206
+ Download the required data for SOLWEIG-GPU from near-globally available urban datasets. Google Earth Engine must be authenticated before this process.
207
+
208
+ ```python
209
+ import os
210
+ from solweig_gpu import build_inputs
211
+
212
+ os.environ["EE_PROJECT"] = "your-gee-project-id" # Your own GEE/GCP project ID
213
+
214
+ base_path = build_inputs(
215
+ lat=latitude,
216
+ lon=longitude,
217
+ city="City name",
218
+ km_buffer=2, # Kilometers from the central lat-lon to set the download extent
219
+ km_reduced_lat=1,
220
+ km_reduced_lon=1,
221
+ base_folder="/path/to/save/inputs",
222
+ resolution=2, # Spatial resolution of the generated rasters in meters
223
+ )
224
+
225
+ print("SOLWEIG input folder:", base_path)
226
+ ```
227
+
228
+ #### Compute direction-based wind coefficients (optional)
229
+
230
+ This requires ERA5 data with the variable `Forecasted surface roughness`.
231
+
232
+ ```python
233
+ from solweig_gpu import build_wind_ext_coeff
234
+
235
+ build_wind_ext_coeff(
236
+ "/path/to/solweig/input", # Base path where input rasters are present
237
+ "/path/to/era5/data_stream-oper_stepType-instant.nc" # ERA5 instantaneous file
238
+ )
239
+ ```
240
+
241
+ #### Example 1: Modular way of running the model with ERA5
242
+
243
+ ##### Step 1: Preprocess and create inputs in the required format
244
+
245
+ - The model simulation date is `2020-08-13`.
246
+ - The start and end dates provided to the model are `2020-08-13 06:00:00 UTC` and `2020-08-14 05:00:00 UTC`, respectively. UTC to local time conversion is handled internally. For Austin, TX, this corresponds to `2020-08-13 01:00:00` to `2020-08-13 23:00:00` local time.
247
+ - The `tile_size` depends on the RAM available on the GPU. A smaller value is safer for lower-memory GPUs, while larger tiles can improve throughput on high-memory GPUs.
248
+ - The `overlap` controls the additional pixels used for shadow transfer between neighboring tiles. For example, with `tile_size=1000` and `overlap=100`, the processed tile size becomes `1100 × 1100` pixels.
249
+
250
+ ```python
251
+ from solweig_gpu import preprocess
252
+
253
+ preprocess(
254
+ base_path="/path/to/solweig/input",
255
+ selected_date_str="2020-08-13",
256
+ building_dsm_filename="Building_DSM.tif",
257
+ dem_filename="DEM.tif",
258
+ trees_filename="Trees.tif",
259
+ landcover_filename="Landuse.tif", # Use None if land cover is not used
260
+ windcoeff_folder="/path/to/solweig/input", # Use None if wind coefficients are not used
261
+ tile_size=400,
262
+ overlap=0,
263
+ use_own_met=False,
264
+ start_time="2020-08-13 06:00:00",
265
+ end_time="2020-08-14 05:00:00",
266
+ data_source_type="ERA5",
267
+ data_folder="/path/to/era5",
268
+ own_met_file=None,
269
+ preprocess_dir="/path/to/solweig/input",
270
+ use_uhi=True, # Use only with ERA5. Calculates diagnostic urban heat island intensity.
271
+ )
272
+ ```
273
+
274
+ ##### Step 2: Calculate wall height and aspect
275
+
276
+ ```python
277
+ from solweig_gpu import run_walls_aspect
278
+
279
+ run_walls_aspect("/path/to/solweig/input")
280
+ ```
281
+
282
+ ##### Step 3: Calculate the sky-view factor
283
+
284
+ ```python
285
+ from solweig_gpu import calculate_svf
286
+
287
+ calculate_svf(
288
+ base_path="/path/to/solweig/input",
289
+ patch_option=2,
290
+ overwrite=False,
291
+ )
292
+ ```
293
+
294
+ ##### Step 4: Run the SOLWEIG-GPU model
295
+
296
+ ```python
297
+ from solweig_gpu import run_utci_tiles
298
+
299
+ run_utci_tiles(
300
+ base_path="/path/to/solweig/input",
301
+ preprocess_dir="/path/to/solweig/input",
302
+ selected_date_str="2020-08-13",
303
+ save_tmrt=True,
304
+ save_svf=False,
305
+ save_kup=False,
306
+ save_kdown=False,
307
+ save_lup=False,
308
+ save_ldown=False,
309
+ save_shadow=False,
310
+ save_wbgt=False,
311
+ )
312
+ ```
313
+
314
+ #### Example 2: Run the model end-to-end with ERA5
315
+
316
+ ```python
317
+ from solweig_gpu import thermal_comfort
318
+
319
+ thermal_comfort(
320
+ base_path="/path/to/solweig/input",
321
+ selected_date_str="2020-08-13",
322
+ building_dsm_filename="Building_DSM.tif",
323
+ dem_filename="DEM.tif",
324
+ trees_filename="Trees.tif",
325
+ landcover_filename="Landuse.tif", # Use None if land cover is not used
326
+ ERA_5_z0_find=True, # If True, expects data_stream-oper_stepType-instant.nc in data_folder
327
+ tile_size=400,
328
+ overlap=0,
329
+ use_own_met=False,
330
+ start_time="2020-08-13 06:00:00",
331
+ end_time="2020-08-14 05:00:00",
332
+ data_source_type="ERA5",
333
+ data_folder="/path/to/era5",
334
+ use_uhi=True,
335
+ save_wbgt=True,
336
+ )
337
+ ```
338
+
339
+ #### Example 3: Run the model end-to-end with WRF
340
+
341
+ This can also be run in the modular way by following Example 1 and replacing `data_source_type` with `wrfout`.
342
+
343
+ ```python
344
+ from solweig_gpu import thermal_comfort
345
+
346
+ thermal_comfort(
347
+ base_path="/path/to/solweig/input",
348
+ selected_date_str="2020-08-13",
349
+ building_dsm_filename="Building_DSM.tif",
350
+ dem_filename="DEM.tif",
351
+ trees_filename="Trees.tif",
352
+ landcover_filename=None,
353
+ ERA_5_z0_find=False, # Set True only if data_folder contains ERA5 data_stream-oper_stepType-instant.nc
354
+ tile_size=3600,
355
+ overlap=20,
356
+ use_own_met=False,
357
+ start_time="2020-08-13 06:00:00",
358
+ end_time="2020-08-14 05:00:00",
359
+ data_source_type="wrfout",
360
+ data_folder="/path/to/wrfout/files",
361
+ own_met_file=None,
362
+ use_uhi=False, # Always keep False when using WRF forcing
363
+ save_tmrt=True,
364
+ save_svf=False,
365
+ save_kup=False,
366
+ save_kdown=False,
367
+ save_lup=False,
368
+ save_ldown=False,
369
+ save_shadow=False,
370
+ save_wbgt=False,
371
+ )
372
+ ```
373
+
374
+ - The model simulation date is `2020-08-13`.
375
+ - The start and end dates provided to the model are `2020-08-13 06:00:00 UTC` and `2020-08-14 05:00:00 UTC`, respectively. These are the start and end times of the WRF output in UTC. In local time, this corresponds to `2020-08-13 01:00:00` to `2020-08-13 23:00:00` for Austin, TX. UTC to local time conversion is handled internally.
376
+ - The `tile_size` depends on the RAM available on the GPU. The value can be reduced for lower-memory GPUs.
377
+ - The `overlap` controls the additional pixels used for shadow transfer between neighboring tiles. For example, with `tile_size=3600` and `overlap=20`, the processed tile size becomes `3620 × 3620` pixels.
378
+ - If `ERA_5_z0_find=True`, SOLWEIG-GPU calculates wind-extension coefficients and expects the ERA5 file `data_stream-oper_stepType-instant.nc` to be available in `data_folder`. If `data_folder` points to WRF output files, keep `data_stream-oper_stepType-instant.nc` in that folder.
379
+
380
+ #### Example 4: Own File
381
+
382
+ ```python
383
+ from solweig_gpu import thermal_comfort
384
+
385
+ thermal_comfort(
386
+ base_path="/path/to/solweig/input",
387
+ selected_date_str="2020-08-13",
388
+ building_dsm_filename="Building_DSM.tif",
389
+ dem_filename="DEM.tif",
390
+ trees_filename="Trees.tif",
391
+ landcover_filename=None,
392
+ ERA_5_z0_find=False, # Set True only if data_folder contains ERA5 data_stream-oper_stepType-instant.nc
393
+ tile_size=3600,
394
+ overlap=20,
395
+ use_own_met=True,
396
+ start_time=None,
397
+ end_time=None,
398
+ data_source_type=None,
399
+ data_folder=None,
400
+ own_met_file="/path/to/met.txt",
401
+ use_uhi=False, # Not recommended with user-provided meteorological files
402
+ save_tmrt=True,
403
+ save_svf=False,
404
+ save_kup=False,
405
+ save_kdown=False,
406
+ save_lup=False,
407
+ save_ldown=False,
408
+ save_shadow=False,
409
+ save_wbgt=False,
410
+ )
411
+ ```
412
+
413
+ - Use this option when forcing SOLWEIG-GPU with a user-provided meteorological `.txt` file.
414
+ - Keep `use_own_met=True` and provide the meteorological file through `own_met_file`.
415
+ - Keep `use_uhi=False` for user-provided meteorological files.
416
+ - If `ERA_5_z0_find=True`, SOLWEIG-GPU expects the ERA5 file `data_stream-oper_stepType-instant.nc` in `data_folder`. Because this example does not use ERA5 forcing, the safer default is `ERA_5_z0_find=False`.
417
+ - If `ERA_5_z0_find=True`, wind directions should be available for each time step in the meteorological `.txt` file.
418
+
419
+ ### Note for Windows Users
420
+ On Windows, Python uses the *spawn* start method for new processes: each worker re-imports your script. Without guarding the entry point, a top-level call to `thermal_comfort()` would run again in every child process, causing repeated execution and failures (e.g. `BrokenProcessPool`). Always call `thermal_comfort()` inside a `main()` function and use `if __name__ == "__main__":` (see example below).
421
+ ```python
422
+ from solweig_gpu import thermal_comfort
423
+ import multiprocessing as mp
424
+
425
+ def main():
426
+ thermal_comfort(
427
+ base_path="/path/to/solweig/input",
428
+ selected_date_str="2020-08-13",
429
+ building_dsm_filename="Building_DSM.tif",
430
+ dem_filename="DEM.tif",
431
+ trees_filename="Trees.tif",
432
+ landcover_filename="Landuse.tif", # Use None if land cover is not used
433
+ ERA_5_z0_find=True, # If True, expects data_stream-oper_stepType-instant.nc in data_folder
434
+ tile_size=400,
435
+ overlap=0,
436
+ use_own_met=False,
437
+ start_time="2020-08-13 06:00:00",
438
+ end_time="2020-08-14 05:00:00",
439
+ data_source_type="ERA5",
440
+ data_folder="/path/to/era5",
441
+ use_uhi=True,
442
+ save_wbgt=True,
443
+ )
444
+
445
+ if __name__ == "__main__":
446
+ mp.freeze_support()
447
+ main()
448
+ ```
449
+ ---
450
+
451
+ ## Command-Line Interface (CLI)
452
+
453
+ #### Example using sample ERA5 data on Windows
454
+
455
+ ```bash
456
+ conda activate solweig
457
+ thermal_comfort --base_path '/path/to/input' ^
458
+ --date '2020-08-13' ^
459
+ --building_dsm 'Building_DSM.tif' ^
460
+ --dem 'DEM.tif' ^
461
+ --trees 'Trees.tif' ^
462
+ --tile_size 1000 ^
463
+ --landcover 'Landcover.tif' ^
464
+ --overlap 100 ^
465
+ --use_own_met False ^
466
+ --data_source_type 'ERA5' ^
467
+ --data_folder '/path/to/era5' ^
468
+ --start '2020-08-13 06:00:00' ^
469
+ --end '2020-08-13 23:00:00' ^
470
+ --era5_z0_find True ^
471
+ --use_uhi True ^
472
+ --save_tmrt True ^
473
+ --save_svf False ^
474
+ --save_kup False ^
475
+ --save_kdown False ^
476
+ --save_lup False ^
477
+ --save_ldown False ^
478
+ --save_shadow False ^
479
+ --save_wbgt True ^
480
+ --save_ta False ^
481
+ --save_wind False
482
+ ```
483
+
484
+ - `--era5_z0_find` computes directional wind-extension coefficients and requires `data_stream-oper_stepType-instant.nc` in `--data_folder`. It defaults to `True` when `--data_folder` is provided and `False` otherwise.
485
+ - `--use_uhi` computes the diagnostic urban heat island intensity; use it only with ERA5 forcing (set `False` for WRF or your own meteorological file).
486
+
487
+ > Tip: Use `--help` to list all CLI options.
488
+
489
+ ---
490
+
491
+ ### Contributing
492
+ Please refer to the [documentation](./docs/developer_guide.md)