A comprehensive, educational Python toolkit covering every building block of a Particle-In-Cell (PIC) plasma simulation — from single-particle pushers to complete electrostatic and electromagnetic PIC codes, advanced diagnostics, and collisional physics, all with animated visualisations.
22 self-contained scripts · NumPy + Matplotlib only · No compilation required
- Overview — The PIC Method
- Physics Background
- Repository Structure
- Module Descriptions
- Requirements
- Quick Start
- How the Pieces Fit Together
- Possible Improvements
- References
- License
The Particle-In-Cell (PIC) method is the workhorse of computational plasma physics. It represents the plasma as a collection of macro-particles and evolves them self-consistently with electromagnetic fields on a grid.
The PIC loop (every time step):
┌─────────────────────────────────────────────────────────┐
│ PIC CYCLE │
│ │
│ 1. CHARGE / CURRENT DEPOSITION │
│ particles → grid (weighting / shape functions) │
│ ↓ │
│ 2. FIELD SOLVE │
│ Poisson (ES) or Maxwell / Yee FDTD (EM) │
│ ↓ │
│ 3. FIELD INTERPOLATION │
│ grid → particles (gather) │
│ ↓ │
│ 4. PARTICLE PUSH │
│ Boris / Vay / Higuera-Cary (leapfrog in time) │
│ ↓ │
│ 5. BOUNDARY CONDITIONS │
│ periodic / reflecting / absorbing │
│ ↓ │
│ 6. (OPTIONAL) COLLISIONS │
│ Monte Carlo Collisions (MCC) │
│ │
│ repeat ────────────────────────────────────────────→ │
└─────────────────────────────────────────────────────────┘
Each script in this repo implements one or more of these steps. The full PIC codes tie them all together.
Non-relativistic:
Relativistic (using proper velocity
| Symbol | Name | Formula |
|---|---|---|
| Electron plasma frequency | ||
| Debye length | ||
| Larmor radius | ||
| Ion acoustic speed |
Boris_Algorithm/
│
│ ── PARTICLE PUSHERS ──────────────────────────────────
├── Non-relativistic-Boris.py # Classical Boris pusher, B-field sweep
├── Relativistic-Boris.py # Relativistic Boris (proper velocity u = γv)
├── Vay-Pusher.py # Vay pusher — Boris vs Vay comparison
├── Higuera-Cary-Pusher.py # 3-way pusher comparison (Boris/Vay/HC)
│
│ ── FIELD SOLVERS ─────────────────────────────────────
├── Poisson-Solver-1D2D.py # 1D tridiagonal & 2D FFT Poisson solvers
├── Yee-FDTD-2D.py # 2D TM-mode FDTD Maxwell solver
│
│ ── PARTICLE–GRID COUPLING ───────────────────────────
├── Particle-Weighting.py # Shape functions (NGP/CIC/TSC), Esirkepov J
├── Binomial-Filter.py # Smoothing filters & transfer functions
│
│ ── COMPLETE PIC CODES ───────────────────────────────
├── PIC-1D-TwoStream.py # 1D electrostatic PIC (two-stream)
├── EM-PIC-1D.py # 1D electromagnetic PIC (laser-plasma)
├── Weibel-Instability.py # 2D EM PIC (Weibel / filamentation)
│
│ ── PLASMA PHYSICS DEMOS ─────────────────────────────
├── Plasma-Oscillation.py # Cold plasma wave, ω_pe measurement
├── Landau-Damping.py # ES PIC, Landau damping rate measurement
├── Ion-Acoustic-Wave.py # Two-species ES PIC (electrons + ions)
├── Magnetic-Mirror.py # Converging B-field, adiabatic invariant μ
├── Debye-Sheath.py # Plasma–wall sheath, Bohm criterion
├── Vlasov-1D1V.py # Semi-Lagrangian Vlasov–Poisson solver
│
│ ── DIAGNOSTICS & ANALYSIS ───────────────────────────
├── Dispersion-Relation.py # Analytical ω(k) + PIC FFT validation
├── Convergence-Analysis.py # Δt / Δx / PPC convergence studies
├── Energy-Conservation.py # Energy, momentum, Gauss's law checks
│
│ ── ADVANCED TECHNIQUES ──────────────────────────────
├── Monte-Carlo-Collisions.py # PIC-MCC: elastic, ionisation, CX
├── Particle-Merging.py # Adaptive particle merging & splitting
│
└── README.md
File: Non-relativistic-Boris.py
The classic Boris algorithm in SI units for an electron in a uniform magnetic field (
| Feature | Detail |
|---|---|
| Particle | Electron ( |
| Initial velocity | |
| B-field | Swept over 10 values (2.2 – 22 T) |
| Output | 6-panel animation + Larmor radius vs |
Boris algorithm steps:
| # | Operation | Formula |
|---|---|---|
| 1 | Half electric kick | |
| 2a | Rotation vectors |
|
| 2b | Magnetic rotation |
|
| 3 | Half electric kick | |
| 4 | Position update |
File: Relativistic-Boris.py
Same Boris splitting, but operates on the proper velocity
| Feature | Detail |
|---|---|
| Initial velocity |
|
| B-field |
|
| Validation | Prints analytical vs numerical Larmor radius |
| Output | 6-panel animation including |
File: Vay-Pusher.py
The Vay pusher (2008) is an alternative to Boris for relativistic regimes, especially when
| Feature | Detail |
|---|---|
| Runs both Boris AND Vay on the same scenario | Side-by-side comparison |
| Diagnostics | Trajectory, |
| Key advantage | Better accuracy at ultra-relativistic speeds |
File: Higuera-Cary-Pusher.py
Three-way comparison of Boris, Vay, and Higuera-Cary pushers in crossed
| Feature | Detail |
|---|---|
| Test case | Crossed |
| Key result | HC gives the correct |
| Plots | Trajectories, drift velocity comparison, Larmor orbit shapes |
File: Poisson-Solver-1D2D.py
Solves
| Method | Domain | Boundary | Algorithm |
|---|---|---|---|
| 1D | Uniform grid | Dirichlet | Thomas (tridiagonal) |
| 1D | Uniform grid | Periodic | FFT |
| 2D | Uniform grid | Periodic | 2D FFT |
File: Yee-FDTD-2D.py
Full 2D Finite-Difference Time-Domain solver for Maxwell's equations on a staggered Yee grid (TM mode:
| Feature | Detail |
|---|---|
| Grid | 200 × 200 |
| Source | Gaussian-modulated sinusoidal pulse |
| Boundary | First-order Mur absorbing BC |
| CFL |
File: Particle-Weighting.py
| Order | Name | Stencil | Smoothness |
|---|---|---|---|
| 0 | Nearest Grid Point (NGP) | 1 cell | Discontinuous |
| 1 | Cloud In Cell (CIC) | 2 cells | |
| 2 | Triangular Shaped Cloud (TSC) | 3 cells |
Also includes Esirkepov current deposition (charge-conserving
File: Binomial-Filter.py
Digital smoothing filters for PIC current/charge densities.
| Filter | Kernel | Key Feature |
|---|---|---|
| 1-2-1 binomial (n-pass) | Simple, broad suppression | |
| Stride-S binomial | Targets specific |
|
| Compensation | Preserves low-$k$ signal | |
| 2D binomial | Tensor product | For 2D/3D PIC |
Includes transfer function analysis in Fourier space.
File: PIC-1D-TwoStream.py
| Feature | Detail |
|---|---|
| Particles | 20 000 macro-electrons |
| Grid | 128 cells, periodic |
| Physics | Two beams at |
File: EM-PIC-1D.py
| Feature | Detail |
|---|---|
| Fields |
|
| Source | Gaussian laser pulse ( |
| Boundary | Mur absorbing BC + particle reflection |
File: Weibel-Instability.py
Two counter-streaming electron beams in 2D generate the Weibel (filamentation) instability: spontaneous growth of magnetic fields perpendicular to the beam direction.
| Feature | Detail |
|---|---|
| Grid | 128 × 128, periodic |
| Particles | 2 × 8 PPC (total ~260 k macro-particles) |
| Beam speed | |
| Growth rate | |
| Diagnostics |
|
File: Plasma-Oscillation.py
Cold plasma with sinusoidal density perturbation. Measures the plasma frequency
File: Landau-Damping.py
100 000-particle ES PIC with Maxwellian distribution + low-amplitude sinusoidal perturbation. Measures the collisionless damping rate and compares to the analytical Landau result:
File: Ion-Acoustic-Wave.py
Two-species (electron + ion) ES PIC with
File: Magnetic-Mirror.py
Single particle in a parabolic mirror field
- Magnetic mirroring (reflection of trapped particles)
- Loss cone (particles escaping through the mirror throat)
- Conservation of the adiabatic invariant
$\mu = m v_\perp^2 / (2B)$
File: Debye-Sheath.py
Plasma bounded by two conducting walls. Both electrons and ions are kinetic with absorbing wall BCs.
| Feature | Detail |
|---|---|
| System length | 50 |
| Mass ratio | |
| Physics | Bohm sheath criterion, self-consistent potential drop |
| Validation | Compares wall potential to Bohm formula: |
| Diagnostics | Potential profile, density profiles, electron & ion phase space |
File: Vlasov-1D1V.py
Grid-based (not PIC!) solver for the Vlasov equation on a
| Feature | Detail |
|---|---|
| Grid | 128 × 256 |
| Method | FFT-based semi-Lagrangian (spectral interpolation) |
| Test case | Landau damping without particle noise |
File: Dispersion-Relation.py
Computes analytical dispersion relations and validates them against PIC simulation data in
| Dispersion | Formula |
|---|---|
| Langmuir (Bohm-Gross) | |
| Light wave | |
| Ion acoustic |
PIC validation: runs a broadband 1D ES PIC, FFTs
File: Convergence-Analysis.py
Systematic sweep of PIC parameters on a cold plasma oscillation benchmark:
| Study | Sweep | Expected Scaling |
|---|---|---|
| Time step |
|
|
| Grid spacing |
|
|
| Particles per cell | PPC |
|
| Energy conservation | Error scaling with time step |
File: Energy-Conservation.py
Standalone diagnostic module monitoring:
| Diagnostic | Quantity |
|---|---|
| Energy components | Kinetic + Field energy vs time |
| Relative error | |
| Momentum | |
| Gauss's law | |
| Charge |
File: Monte-Carlo-Collisions.py
Implements binary collision models for gas-discharge / low-temperature plasmas:
| Collision | Process | Model |
|---|---|---|
| Elastic | Isotropic scattering, energy loss | |
| Ionisation | Threshold |
|
| Charge exchange | Fast ion → slow ion swap |
Uses the null-collision method for efficient sampling. Demo runs a 1D capacitively-coupled plasma (CCP) discharge with RF voltage drive.
Diagnostics: EEDF, IEDF, particle populations, cumulative collision statistics.
File: Particle-Merging.py
Adaptive macro-particle count control:
| Algorithm | Direction | Method |
|---|---|---|
| Merging | Many → Few | Momentum-conserving pairwise merge of close |
| Splitting | Few → Many | Weight-halving with small |
| Adaptive PPC | Both | Maintain PPC within (PPC_min, PPC_max) bands |
Diagnostics: PPC distribution heatmap, merge/split event counts, momentum conservation, weight histogram.
| Package | Version | Purpose |
|---|---|---|
| Python | 3.8+ | Runtime |
| NumPy | any | Array math, FFT |
| Matplotlib | any | Plotting, FuncAnimation |
| SciPy | any | Optional (used in Dispersion-Relation.py for brentq) |
pip install numpy matplotlib scipyEach script is self-contained — just run it:
# ── Particle Pushers ──
python Non-relativistic-Boris.py
python Relativistic-Boris.py
python Vay-Pusher.py
python Higuera-Cary-Pusher.py
# ── Field Solvers ──
python Poisson-Solver-1D2D.py
python Yee-FDTD-2D.py
# ── Particle–Grid Operations ──
python Particle-Weighting.py
python Binomial-Filter.py
# ── Full PIC Simulations ──
python PIC-1D-TwoStream.py
python EM-PIC-1D.py
python Weibel-Instability.py
# ── Plasma Physics Demos ──
python Plasma-Oscillation.py
python Landau-Damping.py
python Ion-Acoustic-Wave.py
python Magnetic-Mirror.py
python Debye-Sheath.py
python Vlasov-1D1V.py
# ── Diagnostics ──
python Dispersion-Relation.py
python Convergence-Analysis.py
python Energy-Conservation.py
# ── Advanced ──
python Monte-Carlo-Collisions.py
python Particle-Merging.pyEach script opens an animated Matplotlib window with multi-panel diagnostics (or static multi-panel plots for analysis scripts).
PIC SIMULATION TOOLKIT
══════════════════════
┌────────────────────────────────────────────────────────────────┐
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Particle-Weighting.py · Binomial-Filter.py │ │
│ │ (deposit ρ, J to grid · smooth) │ │
│ └──────────────────────┬───────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Poisson-Solver-1D2D.py (ES) · Yee-FDTD-2D.py │ │
│ │ (solve for E) (solve for E, B) │ │
│ └──────────────────────┬───────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Particle-Weighting.py │ │
│ │ (interpolate E, B → particle positions) │ │
│ └──────────────────────┬───────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Non-relativistic-Boris.py · Relativistic-Boris.py │ │
│ │ Vay-Pusher.py · Higuera-Cary-Pusher.py │ │
│ │ (advance v, x) │ │
│ └──────────────────────┬───────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Monte-Carlo-Collisions.py (optional collisions) │ │
│ │ Particle-Merging.py (adaptive particles) │ │
│ └──────────────────────┬───────────────────────────────────┘ │
│ ↓ │
│ repeat │
│ │
├────────────────────────────────────────────────────────────────┤
│ COMPLETE CODES: │
│ PIC-1D-TwoStream.py (1D ES) │
│ EM-PIC-1D.py (1D EM) │
│ Weibel-Instability.py (2D EM) │
│ Debye-Sheath.py (1D ES, bounded) │
│ Ion-Acoustic-Wave.py (1D ES, two-species) │
│ Monte-Carlo-Collisions.py (1D ES + MCC) │
├────────────────────────────────────────────────────────────────┤
│ ALTERNATIVE METHODS: │
│ Vlasov-1D1V.py (grid-based Vlasov, no particles) │
├────────────────────────────────────────────────────────────────┤
│ PHYSICS BENCHMARKS: │
│ Plasma-Oscillation.py ω_pe measurement │
│ Landau-Damping.py Collisionless damping │
│ Magnetic-Mirror.py Adiabatic invariant μ │
├────────────────────────────────────────────────────────────────┤
│ DIAGNOSTICS: │
│ Dispersion-Relation.py ω(k) theory vs PIC │
│ Convergence-Analysis.py Δt, Δx, PPC scaling │
│ Energy-Conservation.py Conservation checks │
└────────────────────────────────────────────────────────────────┘
- CLI with
argparse— Acceptdt,N_particles,B,E, etc. from the command line. - OOP refactor — Extract
BorisPusher,PoissonSolver,YeeSolverclasses; share via composition. - Unit tests — Validate Larmor radius, energy conservation, Gauss's law, CFL stability.
- Type hints & docstrings — NumPy-style documentation throughout.
- Higher-order FDTD — Replace 2nd-order Yee with 4th-order spatial stencil.
- PML boundaries — Perfectly Matched Layer instead of Mur ABC for better absorption.
-
Implicit PIC — Direct-implicit or energy-conserving implicit methods (removes
$\omega_{pe} \Delta t < 2$ constraint). -
Relativistic Weibel — Extend
Weibel-Instability.pywith relativistic Boris push. - 3D PIC — Full 3D electromagnetic PIC (computationally intensive but educational).
- Electromagnetic dispersion — Add R-wave, L-wave, Bernstein mode dispersion curves.
-
Save animation — Export
.mp4/.gifviaFFMpegWriterorPillowWriter. - Interactive controls — Matplotlib sliders or Plotly/Dash web app.
-
3D phase-space —
$(x, v_x, v_y)$ scatter plots for orbit topology.
- Numba JIT —
@numba.njiton inner loops for 10–100× speedup. - GPU acceleration — CuPy / JAX for large-scale PIC.
- MPI decomposition — Domain decomposition for distributed-memory HPC.
- J. P. Boris, Relativistic plasma simulation — optimization of a hybrid code, Proc. 4th Conf. Num. Sim. Plasmas (1970).
- C. K. Birdsall & A. B. Langdon, Plasma Physics via Computer Simulation, Taylor & Francis, 2004.
- H. Qin et al., "Why is Boris algorithm so good?", Physics of Plasmas 20, 084503 (2013). doi:10.1063/1.4818428
- J.-L. Vay, "Simulation of beams or plasmas crossing at relativistic velocity", Physics of Plasmas 15, 056701 (2008).
- K. Yee, "Numerical solution of initial boundary value problems involving Maxwell's equations in isotropic media", IEEE Trans. Antennas Propag. 14 (3), 302–307 (1966).
- T. Zh. Esirkepov, "Exact charge conservation scheme for Particle-in-Cell simulation", Comput. Phys. Commun. 135, 144–153 (2001).
- R. W. Hockney & J. W. Eastwood, Computer Simulation Using Particles, CRC Press, 1988.
- A. B. Langdon, "Effects of the spatial grid in simulation plasmas", J. Comput. Phys. 6, 247–267 (1970).
- L. D. Landau, "On the vibrations of the electronic plasma", J. Phys. (USSR) 10, 25 (1946).
- E. S. Weibel, "Spontaneously growing transverse waves in a plasma due to an anisotropic velocity distribution", Phys. Rev. Lett. 2, 83 (1959).
- V. Vahedi & M. Surendra, "A Monte Carlo collision model for the PIC method", Comput. Phys. Commun. 87, 179–198 (1995).
This project is provided for educational purposes. Feel free to use, modify, and distribute.