A one-dimensional, three-velocity electromagnetic particle-in-cell code written in JAX.
Runs on CPU, GPU and TPU, compiles the whole time loop, and is differentiable end to end.
Documentation: jax-in-cell.readthedocs.io
What it does
JAX-in-Cell advances charged pseudo-particles in one spatial dimension and three velocity components under the Lorentz force, and advances the electric and magnetic fields on a staggered (Yee) grid with Maxwell's equations. It provides
- an explicit leapfrog integrator with the Boris pusher (non-relativistic or relativistic), a charge-conserving current deposit and a compensated digital filter;
- an implicit Crank-Nicolson integrator solved by Picard iteration, which conserves energy to round-off and has no light-wave time-step limit;
- electromagnetic or electrostatic (Gauss's law by FFT) field solvers;
- periodic, reflective and absorbing boundaries, chosen separately for particles and fields;
- any number of electron and ion populations, each with its own density, drift, temperature anisotropy and seed;
- gradients of any output with respect to the physical inputs through
jax.grad, and re-execution with new inputs without recompilation.
Everything runs as one XLA program on whatever device JAX finds.
Install
pip install jaxincell
or from source:
git clone https://github.com/uwplasma/JAX-in-Cell
cd JAX-in-Cell
pip install -e .
For a GPU, install the matching JAX wheel first (for example pip install -U "jax[cuda12]").
The package enables 64-bit floating point in JAX when imported.
Run
From the command line, with the built-in defaults or a TOML file:
jaxincell
jaxincell examples/input.toml
From Python:
from jaxincell import Simulation, load_parameters, diagnostics, plot
parameters = load_parameters("examples/input.toml") # or a nested dictionary
sim = Simulation(parameters)
output = sim.run() # compiled on the first call
diagnostics(output) # energies, species split, dominant frequency
plot(output) # animated fields, distributions and phase space
The output is a dictionary of arrays: particle positions and velocities, fields, charge and current densities at every step, plus the derived quantities.
Differentiable inputs can be changed at run time and differentiated:
from jax import grad
import jax.numpy as jnp
def mean_field(drift_speed):
out = sim.run({"electrons": {"electrons0": {"drift_speed_x": drift_speed}}})
return jnp.mean(out["electric_field"][:, :, 0])
grad(mean_field)(6e7)
Examples
The examples/ directory contains scripts for the two-stream instability, Landau
damping, Langmuir waves, the bump-on-tail instability with several populations, the
Weibel instability, a gradient check against finite differences, an optimisation over
an input parameter, an inverse problem solved with forward-mode derivatives, and a
timing study. Each is described in the
documentation.
Bump-on-tail instability with periodic (left) and reflective (right) walls:
Benchmarks
Every figure below is drawn by a script in docs/scripts/ from the code on
main (python docs/scripts/make_all.py); the numbers are in
measurements.json. Theory is the kinetic
dispersion relation of the same drifting Maxwellians
(dispersion.py); the
verification page
explains how each rate is fitted.
1D1V: electrostatic
| case | theory | simulation | script |
|---|---|---|---|
| Landau damping, $k\lambda_D = 0.50$, 300 000 quiet-start electrons | $\gamma = -0.154,\omega_{pe}$, $\omega_r = 1.417,\omega_{pe}$ | $\gamma = -0.144$ (explicit and implicit), $\omega_r = 1.404$ | fig_landau_damping.py |
Two-stream, examples/input.toml, 14 000 particles per species |
$\gamma = 0.106,\omega_{pe}$ | $\gamma = 0.112$; over a scan of 10 drifts, 7 % mean deviation at $N = 32,000$ | fig_two_stream.py, fig_two_stream_scan.py |
| Bump-on-tail, 3 % beam, mode 7 | $\gamma = 0.081$, $\omega_r = 0.990,\omega_{pe}$ | $\gamma = 0.071$, $\omega_r = 0.986$ | fig_bump_on_tail.py |
| Relativistic two-stream, $v_0 = \pm0.8c$ ($\gamma_0 = 1.67$), relativistic and non-relativistic Boris | cold $\gamma = 0.164,\omega_{pe}$ (relativistic, mode 1), $0.352,\omega_{pe}$ (non-relativistic, mode 2) | $\gamma = 0.165$ and $0.348$; $\sum(\gamma-1)mc^2$ + field conserved to $1\times10^{-2}$ by the relativistic pusher, off by 33 % with the non-relativistic one, which pushes 29 % of electrons past $c$ | fig_relativistic.py |
| Energy conservation, two-stream above | exact for Crank-Nicolson | relative error $6\times10^{-14}$ (implicit), $3\times10^{-3}$ (explicit) | fig_explicit_implicit.py |
1D2V: electromagnetic
| case | theory | simulation | script |
|---|---|---|---|
| Weibel, $T_z/T_x = 100$, one run per mode | transverse kinetic dispersion relation, $\gamma_{max} = 0.059,\omega_{pe}$ | 5 of 10 modes fitted, 6 % mean and 9 % largest deviation | fig_weibel.py |
The pusher always advances all three velocity components; no 1D3V case on main is
yet compared with a reference.
Documentation
The documentation contains a tutorial, a user guide with every input parameter and output key, a description of the numerical methods (grid, shape functions, Boris and Crank-Nicolson schemes, deposition, filtering, boundaries, stability limits), comparisons with linear theory, the examples, and the API reference. To build it locally:
pip install -r docs/requirements.txt
sphinx-build -W -b html docs docs/_build/html
Testing
pip install pytest pytest-cov
pytest
The test suite runs on every pull request for Python 3.9 to 3.12, together with a build of the documentation.
Contributing and citing
Bug reports and feature requests go to the
issue tracker, questions to the
discussions, and code through
pull requests; see CONTRIBUTING.md. If you use JAX-in-Cell in
your work, please cite it using the CITATION.cff file (GitHub shows it under
"Cite this repository").
Acknowledgements
JAX-in-Cell was inspired by PiC-Code-Jax by Sean Lim. Development is supported by the National Science Foundation under grant PHY-2409066 and by the UWPlasma group at the University of Wisconsin-Madison.
License
MIT, see LICENSE.
Release files for jaxincell 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jaxincell-0.1.1.tar.gz | 1.7 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jaxincell-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.8 MB
Release files / jaxincell-0.1.1.tar.gz
| Download URL | jaxincell-0.1.1.tar.gz |
|---|---|
| Size | 1.7 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
18dc870f36c8ec66ba1374d433ebb69720673443b32b5d6cdecc8bde87d01d63
|
|
BLAKE2b-256 checksum How to use checksums |
09583249b682165d6d255350c2f266c8a07126062b88cce4838b9ea8e5529b71
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency logRelease files / jaxincell-0.1.1-py3-none-any.whl
| Download URL | jaxincell-0.1.1-py3-none-any.whl |
|---|---|
| Size | 60.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c4bdabeb5fa6ed439f44d041db92b14577a463d43804d1980e5605ca00c32be8
|
|
BLAKE2b-256 checksum How to use checksums |
2e5d2b9560511a4ae5a91cffe3f1adc4781405019e5edb3dd3f35440b097fad0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency log