Skip to main content

JAX-in-Cell JAX-in-Cell

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.

Build and test Documentation build Documentation Coverage PyPI License

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.

Two-stream instability: field energy, growth rate against drift speed, and phase space

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

Explicit and implicit schemes on Landau damping and the two-stream instability: field energy against linear theory, and relative energy error

Two-stream drift scan: run time against particle number on CPU and GPU, and growth rate against drift speed against kinetic theory

Relativistic two-stream instability with the relativistic and non-relativistic Boris pushers: field energy against the cold dispersion relations, relative change of the relativistic and Newtonian energies, and phase space

Bump-on-tail instability: distribution function, growth of mode 7 against theory, and phase space

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

Weibel instability: magnetic field, mode amplitudes and growth rate against the transverse dispersion relation

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)

Source distribution for jaxincell 0.1.1
File Size Uploaded
jaxincell-0.1.1.tar.gz 1.7 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for jaxincell 0.1.1
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page