Model configurations, observation-preparation inputs, and post-processing code accompanying:
Site-scale, Multi-resolution WRF Wind Modeling with Observational Nudging for Methane Emission Monitoring in the Permian Basin Ehsan Kharazmi, Erin Menezes, George Karniadakis, Anantha Sundaram, Arash Fathi arXiv: 2609.19442 — submitted to JGR: Atmospheres
The study builds a multiscale WRF framework for a single oil-and-gas site in the Permian Basin, nesting from 3 km down to 40 m so that the inner domains run in large-eddy-simulation mode. On-site anemometer winds are assimilated by observational (station) nudging on the innermost domain. Relative to the unnudged baseline, nudging reduced wind-speed bias by roughly 65–87% and RMSE by 33–44% at the evaluated sensor locations.
This repository holds the configuration and analysis code needed to reproduce those runs. It does not contain WRF itself, the HRRR forcing archive, or the simulation output (see Data and code not included).
Four one-way/two-way nested domains centered on the site at 32.00703°N, 102.23989°W (Lambert conformal):
| Domain | Grid spacing | Grid points (e_we × e_sn) |
Approx. extent | Turbulence closure (km_opt) |
|---|---|---|---|---|
| d01 | 3 km | 50 × 50 | ~150 km | 2D Smagorinsky (4), YSU PBL |
| d02 | 1 km | 52 × 52 | ~52 km | 2D Smagorinsky (4), YSU PBL |
| d03 | 200 m | 51 × 51 | ~10 km | 1.5-order TKE (2), LES (no PBL scheme) |
| d04 | 40 m | 51 × 51 | ~2 km | 1.5-order TKE (2), LES (no PBL scheme) |
54 vertical eta levels, refined near the surface; 1-minute history output; 5 s parent time step.
Initial and boundary conditions come from hourly HRRR analyses (hrrr.t<HH>z.wrfprsf00.grib2).
source/
├── namelist/ WPS and WRF namelists for every configuration in the paper
├── wrf_nudging/ Sensor observations and the little_R / OBS_DOMAIN inputs for obs nudging
├── wrf_js/ Driver script for the WPS + WRF job
└── plotting/ Post-processing of wrfout files and figure generation
| File | Configuration |
|---|---|
namelist_orig4d_WnewPhys.wps |
WPS namelist (geogrid/ungrib/metgrid) shared by all runs |
..._nonudge_extraEta.input |
Baseline, no observational nudging (16–31 Jan 2025) |
..._nudged4_extraEta_test_1.input |
Obs nudging on d04; sfs_opt=0, feedback=0 (16–18 Jan 2025) |
..._nudged4_extraEta_test_2.input |
As test 1 with sfs_opt=1 (Smagorinsky NBA) on d04; restart run (21–31 Jan 2025) |
..._nudged4_extraEta_test_3.input |
As test 1 with sfs_opt=2 (TKE NBA) on d04 |
..._nudged4_extraEta_test_4.input |
sfs_opt=1 on d04 with two-way nesting (feedback=1) (16–21 Jan 2025) |
Observational nudging is enabled on domain 4 only (obs_nudge_opt = 0,0,0,1), nudging winds only
(obs_nudge_wind, coefficient 0.12 s⁻¹) against OBS_DOMAIN401, with a 180 km horizontal radius of
influence, 0.1 eta vertical radius, and a ±40 min time window.
Before running, edit the history_outname / rst_outname paths and the geog_data_path,
prefix, and fg_name paths to match your system.
csv2littleR.md documents how the on-site anemometer records are converted into the observation file that
WRF's station nudging reads, based on tommz9/python-little_r.
The input is a per-sensor CSV with three columns — datetime (YYYY-MM-DD hh:mm), wind_speed (m s⁻¹),
and wind_direction (degrees) — at 1-minute resolution. The CSVs are combined into a single chronological
little_R file, reformatted to .obsnud, and renamed to OBS_DOMAIN401 (domain 4) in the WRF run directory,
with time_control pointing at it.
The sensor observations themselves are not distributed in this repository; see Data and code not included.
Driver for the full workflow. RUN_WPS / RUN_WRF toggle the two stages. The WPS stage runs geogrid
once, then walks the requested time span in chunks (default 6 h) so that the ungrib intermediates — roughly
3–4 GB per hour for the full HRRR CONUS domain — never accumulate on disk. The WRF stage links the met_em
files, copies the chosen namelist into place, and runs real.exe then wrf.exe under MPI.
nohup bash job_run.sh > log.job 2>&1 &Paths (/WRF/WPS, /WRF/WRF/test/em_real, the HRRR archive root) and MPI rank counts are hard-coded near
the top and need adjusting for your environment.
4dom_preprocessing.py— reads the hourlywrfoutfiles with wrf-python, extracts near-surface levels (below 60 m AGL by default) for the requested domains, concatenates across time, and caches the result as a.npydictionary.4dom_plotting_overlay.ipynb— produces the comparison and overlay figures from those cached arrays.
Requires numpy, netCDF4, wrf-python, pandas, and matplotlib.
- Build WRF/WPS (ARW, 4 domains, LES-capable) and stage the HRRR GRIB archive as
<BASE>/<YYYYMMDD>/hrrr.t<HH>z.wrfprsf00.grib2. - Copy
source/namelist/namelist_orig4d_WnewPhys.wpsto your WPS directory, fix the paths, and run the WPS stage ofjob_run.shto generatemet_emfiles. - Build the observation file from your sensor CSVs following
source/wrf_nudging/csv2littleR.md, and place it in the WRF run directory asOBS_DOMAIN401. - Copy the desired namelist from
source/namelist/tonamelist.input, fix the output paths, and run the WRF stage. - Point
4dom_preprocessing.pyat the output directory, then run4dom_plotting_overlay.ipynb.
- The WRF/WPS source and the WPS geographical static data (
WPS_GEOG) — obtain from NCAR/UCAR. - HRRR GRIB2 forcing files — available from NOAA.
- Raw
wrfouthistory files, which are far too large to distribute here. - The on-site anemometer records used for observational nudging, and the
.obsnudfile assembled from them. Substituting your own sensor data in the CSV format described insource/wrf_nudging/csv2littleR.mdwill reproduce the workflow.
See CITATION.cff, or cite the arXiv preprint directly.
MIT.