The SpeedUp mentioned is bound to varry with testing situation, power, compute capability and hardware
WHISTLER is a high-performance, heterogeneous physics simulation engine designed to model the dispersion of Very Low Frequency (VLF) radio waves (whistlers) in the Earth's plasmasphere. Born from lightning strikes, these electromagnetic transients travel along Earth's magnetic field lines into space and back, getting dispersed such that higher frequencies arrive before lower frequencies.
Note: This project is an explicitly simplified engineering simulation utilizing a bounded frequency-dependent phase delay, not a full Earth magnetospheric cold-plasma wave solver.
This project implements a complete digital signal processing (DSP) pipeline that models this complex physical phenomenon from scratchβincorporating multi-path propagation, additive white Gaussian noise (AWGN), and Short-Time Fourier Transforms (STFT). By offloading the massive frequency-domain phase rotations to standard CUDA cores on the GPU, the engine achieves a 17.3x compute-path performance speedup (when data is resident on the GPU), with a mathematically identical validation error of approximately
π Read the Full Paper: WHISTLER: Computational Modeling of Lightning-Generated Whistlers
- Core DSP Engine: C (Custom Radix-2 FFT, STFT, Hann Windowing, Pulse Generation, Box-Muller AWGN)
- Compute Acceleration: CUDA (Massively parallel frequency-domain phase dispersion)
- Visual & Audio Processing: Python (Matplotlib, Wave, Struct)
The engine executes a sequential data-flow pipeline designed to seamlessly pass memory buffers between the CPU and GPU:
graph TD
A[Pulse Generation C] --> B[FFT C]
B --> C{PCIe Transfer to VRAM}
C --> D[apply_dispersion_kernel CUDA]
D --> E{PCIe Transfer to RAM}
E --> F[IFFT C]
F --> G[Multipath + AWGN C]
G --> H[STFT Hann Window C]
H --> I[(Binary Data Dump)]
I --> J[Python plot.py]
style D fill:#76B900,stroke:#333,stroke-width:2px,color:#fff
style A fill:#00599C,stroke:#333,stroke-width:2px,color:#fff
style J fill:#3776AB,stroke:#333,stroke-width:2px,color:#fff
- Pulse Generation (C): A broadband damped transient simulating a lightning strike is generated in the time domain.
- Frequency Domain (C): A custom Radix-2 FFT transforms the pulse into the frequency domain.
-
Plasma Dispersion (CUDA): The frequency bins are copied to the GPU. A massively parallel CUDA kernel applies the physical dispersion equation
$\tau(f) = t_0 + D f^{-1/2}$ to rotate the phase of every bin simultaneously. - Multipath & Noise (C): The dispersed signal is returned to the CPU, converted back to the time domain via IFFT, combined with an attenuated secondary echo path, and injected with AWGN.
- STFT Spectrogram (C): The engine chunks the signal using a Hann window and computes a rolling STFT to generate a raw waterfall array.
-
Visualization & Audio (Python): Python ingests the binary blobs to generate a 16-bit PCM
.wavaudio file, static high-resolution spectrograms, and dynamic animated GIFs.
WHISTLER/
βββ Makefile # C/CUDA build orchestrator
βββ README.md # Project overview and instructions
βββ docs/
β βββ paper.md # Full research paper and mathematical model
βββ include/
β βββ whistler_core.h # C/CUDA function prototypes and structs
βββ src/
β βββ core/ # C DSP Engine (FFT, STFT, Pulse, Noise)
β βββ cuda/ # CUDA Kernels (Parallel Phase Dispersion)
β βββ python/ # Python plotting, animation, and audio generation
βββ data/ # Generated artifacts (.wav, .png, .gif, .bin)
To run the full heterogeneous pipeline, you need an environment with both a C/CUDA compiler stack and a Python environment for visualization.
- Compiler:
gcc(for C host code) andnvcc(for CUDA device code, explicitly targeting-arch=sm_75). - Hardware: Any NVIDIA GPU supported by your installed CUDA toolkit (Tested on Turing architecture SM_75 and newer). Tensor Cores are explicitly avoided for single-precision accuracy.
- Python Environment: Python 3.10+
- Libraries:
numpy,matplotlib,scipy
- Libraries:
Use the provided Makefile to compile the C and CUDA source files into the executable binary:
make clean
makeRun the compiled binary to execute the physics engine. It will output the CPU/GPU validation metrics, benching results, and dump the raw binary data into the /data directory:
./whistler_m1This runs the default, hardcoded physics model. If you wish to parameterize the simulation environment dynamically, use the separated CLI module:
./whistler_cli -p 3 -n 0.01 -d 20.0-p: Number of Multipaths to simulate (default: 2)-n: AWGN Noise level (default: 0.005)-d: Base Dispersion Constant (default: 15.0)
You can also run the full deterministic regression test suite:
make testOnce the C/CUDA engine has dumped the binary files, execute the Python script to consume the data and generate the audio and spectrograms:
python src/python/plot.pyThis will populate the /data folder with the final whistler.wav, waterfall_static.png, and waterfall_animated.gif artifacts.
The test suite consists of five core regression validations.
| Test | Description | Requires GPU? | Expected Outcome |
|---|---|---|---|
| FFT/IFFT Round Trip | Verifies the custom C FFT matches the original signal after IFFT. | No | Maximum error < 1e-4 |
| CPU vs CUDA Equivalence | Validates the GPU phase dispersion against the CPU scalar reference. | Yes | Mathematical parity (error ~ 1e-6) |
| Low-Frequency Stability | Checks for singularities (NaN/Inf) at DC frequencies. | No | Passed (no NaNs) |
| Full-Pipeline Regression | Runs a deterministic end-to-end trace with a known checksum. | No | Passed (Checksum match) |
| CUDA Kernel Scaling | Assesses execution scaling of the GPU kernel across massive FFT sizes. | Yes | Output bounded scaling limits |
CUDA (Compute Unified Device Architecture) is utilized because the frequency-dependent phase rotations (
Hardware Notes:
- The codebase explicitly avoids Tensor Cores, standardizing on pure FP32 ALU execution to prevent matrix-multiply fast-math drift.
- The pipeline distinctly measures GPU-resident compute speedups (timed explicitly via
cudaEvent_tat the kernel boundary) versus End-to-End Execution (which includes the PCIe VRAM transfer overheads viacudaMemcpyand is timed usingclock_gettime(CLOCK_MONOTONIC)on the host).
- FFT Size: 16,384 bins.
- Workload: 100,000 iterations for resident benchmarking, 1,000 iterations for E2E benchmarking.
- Hardware: NVIDIA RTX 5060 (SM_120) was used to achieve the primary benchmark numbers. (Continuous Integration tests run on NVIDIA T4 (SM_75) Google Colab instances).
- Result: The 17.3x Speedup represents the compute-path / GPU-resident execution velocity. The full E2E execution maintains a positive but smaller speedup due to PCIe bandwidth constraints.
To automatically test CUDA code in a Continuous Integration (CI) environment, this project utilizes a custom self-hosted GPU runner.
Because standard GitHub-hosted runners lack NVIDIA hardware, the repository includes colab_runner.ipynb. By spinning up a free Google Colab T4 instance and executing the notebook, a temporary self-hosted GitHub Actions runner is securely connected to the repository to process the gpu CI job.
The physics engine writes binary files using explicit 32-bit little-endian types for portability.
- Audio (
data/audio.bin):- Magic:
"WAVA"(4 bytes) - Version:
1(int32_t) - Sample Rate:
fs(float32) - Length:
len(int32_t) - Payload:
lenelements of IEEE-754float32PCM data.
- Magic:
- Spectrogram (
data/spectrogram.bin):- Magic:
"SPEC"(4 bytes) - Version:
1(int32_t) - Sample Rate:
fs(float32) - Frames:
N(int32_t) - Bins:
M(int32_t) - Payload:
N * Melements of IEEE-754float32data.
- Magic:
- Random Seed: The regression tests use a deterministic seed (Custom Linear Congruential Generator starting at seed
42). - Compilers: Tested with
gcc 11+andnvcc(CUDA 11.4+). - Hardware: NVIDIA Turing Architecture (SM_75) or newer required.
- Results Verification: Running
make testwill validate mathematical fidelity. Running./whistler_m1will output the precise CPU and GPU runtime benchmarks.
- Frequency-Dependent Delay Model: This is an explicit, localized engineering simulation utilizing a bounded frequency-dependent phase delay, not a full Earth magnetospheric cold-plasma wave solver.
-
Numerical Approximations: The single-precision (IEEE-754 binary32) formats can exhibit minor platform-dependent drift (error bounded to
$<10^{-4}$ ).
WHISTLER demonstrates the sheer computational power of heterogeneous architectures for physics modeling. By delegating purely parallel arithmetic to the GPU and keeping sequential orchestration and signal structuring on the CPU, we drastically reduced execution time while maintaining strict numerical parity. It stands as a robust artifact of low-level digital signal processing, high-performance computing, and cross-language integration.
This project is licensed under the MIT License - see the LICENSE file for details.