A high-performance 3D FDTD solver for Maxwell's equations in C++ with OpenMP parallelization, Roden-Gedney PML absorbing boundaries, and Rerun-based 3D visualization.
AC current loop radiating electromagnetic waves, visualized with Rerun. E-field in viridis, H-field in inferno.
Implements the Yee algorithm on a staggered grid using leapfrog time-stepping in H-field formulation with per-cell material coefficients.
Discretized with precomputed loss-incorporating coefficients:
where
The time step satisfies the CFL condition:
- Yee-grid leapfrog with per-cell ε, μ, σ and precomputed Ca/Cb/Db coefficients via public
bake_coefficients() - Roden-Gedney PML absorbing boundaries (σ/α grading with κ = 1; no coordinate stretching), per-axis σ_max for anisotropic grids, and material-correct ψ application using per-cell Cb/Db
- Monolithic
AlignedSoA<T>memory - 27 field/material/coefficient arrays in one SIMD-aligned contiguous block with compile-time width detection (AVX-512/AVX2/SSE2) - OpenMP parallelization with
collapse(2)outer loops,#pragma omp simdinner loops,RESTRICT/ASSUME_ALIGNEDhints - Four source types: AC current loop, AC concentric rings, straight wire, point source, Gaussian pulse
- Double-buffered binary I/O with persistent writer thread overlapping computation
- Plane wave validation tracking energy drift, phase correlation, and numerical dispersion
- Rerun 3D visualization with volume rendering, vector cones, and time-series energy plots
- Tests across 7 suites including analytical curl checks, multi-axis PML reflection (dB), non-unity material regression, lossy baking, independent H/E half-step verification, and anisotropic coefficient validation
| Dependency | Version | Required | Purpose |
|---|---|---|---|
| C++ compiler (GCC recommended) | C++23 | Yes | Solver |
| CMake | ≥ 3.20 | Yes | Build system |
| OpenMP | — | Yes | Parallelization |
| Python | ≥ 3.x | No | Visualization only |
| NumPy | — | No | Visualization only |
| Rerun SDK | — | No | Visualization only |
mkdir -p build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j
./main
python ../render.py # optional visualizationWindows (MinGW):
cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release
mingw32-make -jThe scripts/ directory has per-mode scripts for both platforms. Each creates its build directory on first run and does incremental builds on subsequent runs.
Linux / macOS:
./scripts/build-debug.sh
./scripts/build-test.sh
./scripts/build-release.shWindows (PowerShell / MinGW):
.\scripts\build-debug.ps1
.\scripts\build-test.ps1
.\scripts\build-release.ps1| Mode | Flags | Tests | Use Case |
|---|---|---|---|
| Debug | -O0 -g3, ASan+UBSan (Linux/macOS) |
Yes | Bug hunting |
| Test | -O3 -march=native (lib), -O2 (tests, no -ffast-math) |
Yes | Correctness |
| Release | -O3 -march=native -ffast-math -flto |
No | Benchmarking |
cmake .. -DCMAKE_BUILD_TYPE=Test
make -j
ctest --output-on-failure
# or run individual suites:
./run_tests PML
./run_tests IntegrationParameters in config.cfg (key = value, # comments). Missing keys use compiled defaults; unknown keys warn.
| Parameter | Description | Default |
|---|---|---|
Nx, Ny, Nz |
Grid cell count per axis | 100 |
dx, dy, dz |
Spatial step size | 1.0 |
eps, mu |
Permittivity and permeability | 1.0 |
cfl_factor |
CFL stability factor (0 < α ≤ 1) | 1.0 |
total_steps |
Number of time steps | 1000 |
run_validation |
Run plane wave test on startup | true |
use_pml |
Enable PML boundaries | true |
pml_order |
Polynomial grading order | 3 |
pml_alpha_max |
Maximum α frequency shift | 0.3 |
Derived: dt (CFL-limited), pml_thickness (from grid volume, clamped to [4, 25]), pml_sigma_max_x/y/z (per-axis Berenger formula).
├── config.cfg # Runtime parameters
├── CMakeLists.txt # Three-tier build system
├── render.py # Rerun 3D visualization
├── scripts/
│ ├── build-debug.{sh,ps1} # Debug build
│ ├── build-test.{sh,ps1} # Test build
│ └── build-release.{sh,ps1} # Release build
├── src/
│ ├── main.cpp # Entry point
│ ├── Utilities/
│ │ ├── aligned_soa.hpp # SIMD-aligned SoA allocator
│ │ └── macros.hpp # RESTRICT, ASSUME_ALIGNED macros
│ └── Classes/
│ ├── Config/config.hpp # Config parser & derived quantities
│ ├── Grid/grid.{hpp,cpp} # Field storage, Yee kernels, bake_coefficients
│ ├── Source/source.{hpp,cpp} # Source types (loop, wire, point, Gaussian)
│ ├── PML/pml.{hpp,cpp} # PML coefficients & ψ updates
│ ├── Simulation/simulation.{hpp,cpp}
│ ├── Write_Output/output.{hpp,cpp}
│ └── Validation/validation.{hpp,cpp}
├── tests/
│ ├── test_framework.hpp # Header-only test framework
│ ├── test_aligned_soa.cpp # Allocation & alignment (7)
│ ├── test_grid.cpp # Grid, sources, config, lossy, H/E split (19)
│ ├── test_pml.cpp # Coefficients, anisotropic, clamping (9)
│ ├── test_integration.cpp # Physics: conservation, causality, dipole, superposition (14)
│ └── test_output_validation.cpp # I/O, validation, multi-axis PML reflection (6)
└── output/ # Generated data (gitignored)


