# gprMax: three decades of FDTD, from GPR to general time-domain electromagnetics

> gprMax is a GPLv3 licensed finite-difference time-domain solver written in Python with Cython for the hot paths, born in 1990s ground penetrating radar research and now a general research platform for time-domain computational electromagnetics. The judgement is that its physics breadth and acceleration backends are its strength, and that mesh cost and the copyleft licence are the two constraints a new user hits first.

**gprMax/gprMax** — gprMax is open source software that simulates electromagnetic wave propagation using the Finite-Difference Time-Domain Finite-Difference (FDTD) code for numerical modelling of Ground Penetrating Radar (GPR), antennas, radar and bioelectromagnetics

- Repository: https://github.com/gprMax/gprMax
- Website: https://www.gprmax.org
- Stars: 893 · Forks: 402
- Language: Python
- License: GPL-3.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/gprmax-gprmax

## From a 1997 D.Phil. thesis to a general EM platform

gprMax began as research into the forward problem of ground penetrating radar in the 1990s. Antonis Giannopoulos created the original code and established its numerical foundations, documented in his 1997 D.Phil. thesis, and GPR remains the application that gives the software its name. The open source Python and Cython codebase that became version 3 was led by Craig Warren, building on his doctoral research, and Iraklis Giannakis contributed major developments in dispersive medium modelling, fractal media and realistic GPR models, work the two of them described in a 2016 Computer Physics Communications paper. The version 4 line came from John Hartley's doctoral research on subgridding, and Nathan Mannall then carried out a major architectural refactoring and developed the MPI domain decomposition solver, while Qifeng Shen built the FDFD eigenmode solver, wave-port and impedance boundary capabilities and led the expansion into antenna and RF modelling. After nearly three decades the version 4 codebase extends well beyond the 2016 paper, and the README now describes it as a general-purpose research platform for time-domain computational electromagnetics.

## Two front ends over one package

The same engine is reachable two ways, and the repository layout shows how that is arranged. gprMax supports two and three dimensional models through a Python API and through a text-based input-file interface, so a study can be scripted or written as a declarative file. The main package lives in gprMax/ and holds model construction, media and source definitions, the CPU and accelerator solvers, MPI domain decomposition, subgridding, FDFD eigenmode ports, near-to-far-field transforms and the antenna and port machinery, with a toolboxes directory alongside. The examples directory is grouped by application, with separate folders for antennas, features, gpr, jupyter-notebooks and rcs, and those examples are also shipped as package resources so they stay available to users who install a binary wheel rather than a source checkout. Documentation sources sit in docs/, written in reStructuredText with Sphinx and published through Read the Docs, and the repository also carries conda_env.yml, requirements.txt, setup.py, pyproject.toml, build_config.py and packaging_config.py, plus separate tests, testing and reframe_tests directories.

## The physics the model can express

The feature list in the README is dense, and it is the best available summary of what the solver can represent. On the geometry side there is dielectric smoothing, semantic object tags, imported voxel geometries, fractal media and locally refined subgrids. The media library covers conductive, anisotropic, magnetic and multipole dispersive media, with reusable media databases and dispersive interface averaging, which is the numerical trick that lets a dispersive medium sit against another one without spurious reflections. Excitation is not limited to a simple dipole, since the solver offers dipole, voltage, transmission-line, magnetic-frill, plane-wave, rational network and FDFD eigenmode-port sources. The output side is what a working group actually consumes: port quantities, multi-case studies, S-parameters, impedance, antenna gain and directivity, radar cross section, near and far-field transforms, SAR and radiometric absorbed power. The 2016 paper describes an earlier generation of these capabilities, so the current documentation is the reference for what is actually in version 4.

## Acceleration is a menu of backends

gprMax is written principally in Python 3, with performance-critical parts in Cython, and the acceleration story is a set of options rather than a single path. Shared-memory CPU execution uses OpenMP, CPU and GPU execution can use OpenCL, NVIDIA GPUs can use CUDA, and Apple GPUs use Metal on macOS with M-series chips. Larger scale runs are handled with MPI support through mpi4py, which enables multi-node simulations through domain decomposition. The point of the design is stated as common model-building and output interfaces, so the same model file runs on any backend, which matters when a research group has a mix of hardware. The wheel build configuration shows how that portability is handled in practice, since the CI builds for CPython 3.11, 3.12 and 3.13, skips musllinux and win32 targets, and runs a smoke test with the matplotlib Agg backend and a single OpenMP thread.

```toml
[tool.cibuildwheel]
build = ["cp311-*", "cp312-*", "cp313-*"]
skip = ["*-musllinux_*", "*-win32"]
build-verbosity = 1
test-command = "python {project}/tests/wheel_smoke.py"
test-environment = { MPLBACKEND = "Agg", OMP_NUM_THREADS = "1", PYTHONFAULTHANDLER = "1" }
```

## Installing from a checkout, one backend at a time

The requirements file documents the installation path, including the optional pieces as pip extras rather than as one heavy dependency set. The base install pulls the scientific stack, with numpy, scipy, h5py, matplotlib, pandas, pillow, jinja2, pytest and the usual supporting packages. MPI domain decomposition and task farming are optional and come from the mpi extra, distributed fractal generation from the mpi-fractals extra, and the accelerator bindings are installed one backend at a time, cuda, opencl or metal, where the metal extra is macOS only, with an accelerators convenience extra that requests every backend applicable to the current platform and may need CUDA or OpenCL system software.

```bash
pip install -e ".[cuda]"
pip install -e ".[opencl]"
pip install -e ".[metal]"       # macOS only
```

The repository also ships a conda_env.yml, and the ReFrame test suite used for HPC validation needs reframe-hpc installed separately, which the requirements file leaves commented out. The point for a new user is that you do not have to decide on a backend before the code works, only before you run a large model.

## The mesh is the budget, and the test suite admits it

The honest limitation of this class of software is that cost scales with resolution, and gprMax is candid about it. The pytest configuration in pyproject.toml defines markers that name the cost directly, with a unit marker for tests that do not execute a complete model, an integration marker for tests that do, a gpu marker for tests that require execution on a real GPU device, and a slow marker for tests that normally take more than ten seconds on a development machine. A full-wave FDTD code has to resolve the wavelength and the detail of the medium inside the domain, so a model that resolves a fractal medium or a fine subgrid is not a small change in runtime, it is a different category of problem. The subgridding and interface averaging work exists precisely to keep that cost in check, but it does not remove it. The second limitation is legal rather than numerical, since the code is released under the GNU General Public License v3 or higher, and any derivative or distributed work inherits that obligation, which rules out dropping the solver into a closed-source commercial product without a different arrangement.

## Citation, licence and the pace of releases

The project asks users to cite it, and the mechanism is specific. The README names the reference to use, Warren, Giannopoulos and Giannakis from 2016 in Computer Physics Communications, and points to a publications section on the website for further guidance, with a CITATION.cff file at the repository root for tooling that reads it automatically. The licence is GNU GPL v3 or higher, and the setup.py file carries a copyright header naming the University of Edinburgh, United Kingdom, with a 2015 to 2026 range. On the release side, the tags are v4.0.0 on 2026-09-14 and v4.0.1 on 2026-10-03, both titled with the Caol Ila release name, and the previous v3.1.7 from 2024-01-03. The last push was on 2026-10-21 and the repository is not archived, so the version 4 line is where the new work is landing, with the older version 3 tag showing how long the gap between the two was. The documentation site is at docs.gprmax.com and the project home is gprmax.org, and the README credits the wider gprMax community and Google Summer of Code contributors for work on accelerators, testing infrastructure, geometry importers, toolboxes and antenna models.

## Conclusion

gprMax is worth adopting for research groups and engineering teams who need full-wave time-domain modelling of GPR, antennas, scattering or bioelectromagnetics and want a Python API they can script, with GPU and MPI backends available when the mesh demands it. It is the wrong choice if you need a closed-source commercial product, since the code is GPLv3 or higher, or if you need a fast approximate answer, since FDTD resolves wavelength and mesh rather than approximating around it. Before you commit, run one of the supplied example models on your hardware to measure the wall clock cost at your intended resolution, and read the performance section of the documentation, because the backend you choose changes that cost by more than any modelling decision.

## FAQ

### How do I install gprMax with GPU acceleration?

The accelerator bindings are optional extras, installed one backend at a time, for example pip install -e ".[cuda]" for NVIDIA GPUs, pip install -e ".[opencl]" for OpenCL and pip install -e ".[metal]" for Apple GPUs on macOS. The ".[accelerators]" convenience extra requests every backend applicable to the current platform and may require CUDA or OpenCL system software.

### What can gprMax simulate besides ground penetrating radar?

The README describes gprMax as a general-purpose research platform for time-domain computational electromagnetics, with applications including antenna and microwave modelling, electromagnetic scattering and radar cross section, bioelectromagnetics and dosimetry, and radiometry. Excitation types include dipoles, magnetic frills, plane waves and FDFD eigenmode ports.

### Can gprMax run a simulation across multiple machines?

Yes. MPI support through mpi4py enables multi-node simulations, and the repository includes an MPI domain decomposition solver developed by Nathan Mannall. The MPI capability is an optional extra, installed with pip install -e ".[mpi]", and the ReFrame test suite for HPC validation is in the reframe_tests directory.

## Sources

- [gprMax/gprMax on GitHub](https://github.com/gprMax/gprMax)
- [License: GPL-3.0](https://github.com/gprMax/gprMax/blob/master/LICENSE)
- [Project website](https://www.gprmax.org)
- [README](https://github.com/gprMax/gprMax/blob/master/README.md)
- [Releases](https://github.com/gprMax/gprMax/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/gprmax-gprmax
