pycharge#

PyCharge: Electromagnetics simulation library for moving point charges built on JAX.

Submodules#

Classes#

Charge

Point charge with time-dependent trajectory.

SolverConfig

Numerical solver configuration stored in Charge.

Source

Electromagnetic source used in electrodynamics simulations.

Functions#

dipole_source(d_0, omega_0, origin[, q, m])

Create harmonic dipole oscillator with radiation damping.

free_particle_source(position_0_fn[, q, m])

Create free charged particle subject to Lorentz force.

potentials_and_fields(charges)

Create function to compute Liénard-Wiechert potentials and fields from moving charges.

simulate(sources, ts[, print_every])

Create simulation function for time-evolution of interacting electromagnetic sources.

Package Contents#

class pycharge.Charge#

Point charge with time-dependent trajectory.

position_fn#

Position function \(\mathbf{r}(t)\) mapping time (s) to position (m). Must be twice differentiable.

Type:

Callable[[Scalar], Vector3]

q#

Charge (C). Default: e (elementary charge \(\approx 1.602 \times 10^{-19}\) C).

Type:

float

solver_config#

Solver configuration. Default: SolverConfig().

Type:

SolverConfig

Note

Velocity \(\mathbf{v} = d\mathbf{r}/dt\) and acceleration \(\mathbf{a} = d^2\mathbf{r}/dt^2\) computed via JAX autodiff for Liénard-Wiechert calculations.

class pycharge.SolverConfig#

Numerical solver configuration stored in Charge.

Parameters for the two-stage solver in emission_time(), which uses fixed-point iteration followed by Newton’s method.

fixed_point_rtol#

Relative tolerance for fixed-point iteration. Default: 0.0.

Type:

float

fixed_point_atol#

Absolute tolerance for fixed-point iteration. Default: 1e-20.

Type:

float

fixed_point_max_steps#

Maximum iterations for fixed-point iteration. Default: 256.

Type:

int

fixed_point_throw#

Raise exception on failure for fixed-point iteration. Default: False.

Type:

bool

root_find_rtol#

Relative tolerance for Newton’s method. Default: 0.0.

Type:

float

root_find_atol#

Absolute tolerance for Newton’s method. Default: 1e-20.

Type:

float

root_find_max_steps#

Maximum iterations for Newton’s method. Default: 256.

Type:

int

root_find_throw#

Raise exception on failure for Newton’s method. Default: True.

Type:

bool

class pycharge.Source#

Electromagnetic source used in electrodynamics simulations.

Encapsulates charges and equations of motion for use with simulate().

charges_0#

Initial charges for time-dependent simulation.

Type:

Sequence[Charge]

ode_func#

ODE function (t, u, other_charges) -> du/dt where u has shape (n_charges, 2, 3) for [[[x0, y0, z0], [vx0, vy0, vz0]], [[x1, y1, z1], [vx1, vy1, vz1]], ...].

Type:

Callable

pycharge.dipole_source(d_0, omega_0, origin, q=e, m=m_e)#

Create harmonic dipole oscillator with radiation damping.

Two charges \(\pm q\) oscillate as damped harmonic dipole with radiation reaction. Equation of motion for dipole moment \(\mathbf{d} = q(\mathbf{r}_+ - \mathbf{r}_-)\):

\[\ddot{\mathbf{d}} + \gamma_0 \dot{\mathbf{d}} + \omega_0^2 \mathbf{d} = \frac{q^2}{m} \mathbf{E}_{\text{ext}}\]

where \(\gamma_0 = \frac{q^2\omega_0^2}{6\pi\epsilon_0 c^3 m}\) is the damping coefficient.

Parameters:
  • d_0 (Vector3) – Initial dipole separation \(\mathbf{d}_0\) (m).

  • omega_0 (float) – Natural frequency (rad/s).

  • origin (Vector3) – Center position (m).

  • q (float) – Charge magnitude (C) of each charge. Charges are \(+q\) and \(-q\). Default: e.

  • m (float) – Mass (kg) of each charge. Effective (reduced) mass is \(m/2\). Default: m_e.

Returns:

Source with two charges and dipole ODE.

Return type:

Source

Note

Dipole responds only to electric field along polarization axis.

pycharge.free_particle_source(position_0_fn, q=e, m=m_e)#

Create free charged particle subject to Lorentz force.

Particle evolves according to \(m\frac{d\mathbf{v}}{dt} = q(\mathbf{E} + \mathbf{v} \times \mathbf{B})\).

Parameters:
  • position_0_fn (Callable[[Scalar], Vector3]) – Initial position function \(\mathbf{r}_0(t)\).

  • q (float) – Charge (C). Default: e.

  • m (float) – Mass (kg). Default: m_e.

Returns:

Source with one charge and Lorentz force ODE.

Return type:

Source

pycharge.potentials_and_fields(charges)#

Create function to compute Liénard-Wiechert potentials and fields from moving charges.

Returns a function that calculates electromagnetic potentials and fields at spacetime points.

The Liénard-Wiechert potentials:

\[\varphi(\mathbf{r}, t) = \left[\frac{q}{4\pi\varepsilon_0} \frac{1}{(1 - \boldsymbol{\beta}_s \cdot \mathbf{n}_s) R}\right]_{t_r},\]
\[\mathbf{A}(\mathbf{r}, t) = \frac{\boldsymbol{\beta}_s(t_r)}{c} \varphi(\mathbf{r}, t).\]

The electric and magnetic fields:

\[\mathbf{E}(\mathbf{r}, t) = \frac{q}{4\pi\varepsilon_0} \left[ \frac{\mathbf{n}_s - \boldsymbol{\beta}_s}{\gamma^{2}(1-\boldsymbol{\beta}_s \cdot \mathbf{n}_s)^{3}\,R^{2}} \;+\; \frac{\mathbf{n}_s \times \bigl\{(\mathbf{n}_s - \boldsymbol{\beta}_s) \times \dot{\boldsymbol{\beta}}_s\bigr\}}{c\,(1-\boldsymbol{\beta}_s \cdot \mathbf{n}_s)^{3}\,R} \right]_{t_r},\]
\[\mathbf{B}(\mathbf{r}, t) = \frac{\mathbf{n}_s(t_r)}{c} \times \mathbf{E}(\mathbf{r}, t),\]

where all source quantities are evaluated at \(t_r\).

Parameters:

charges (Iterable[Charge]) – Charge object(s) to compute fields from.

Returns:

Function (x, y, z, t)

returning electromagnetic quantities at spacetime point.

Return type:

Callable[[ArrayLike, ArrayLike, ArrayLike, ArrayLike], Quantities]

Note

Compatible with JAX transformations (jax.jit(), jax.grad()).

pycharge.simulate(sources, ts, print_every=100)#

Create simulation function for time-evolution of interacting electromagnetic sources.

Uses RK4 time-stepping with trajectory interpolation to solve the corresponding equations of motion.

Parameters:
  • sources (Sequence[Source]) – Sources to simulate.

  • ts (Array) – Time points, shape (n_steps,).

  • print_every (int) – Print progress every N steps. Set to 0 to disable. Default: 100.

Returns:

Function returning tuple of state arrays, one per source.

Each state array has shape (n_steps, n_charges, 2, 3) for [[r, v], ...] at each time.

Return type:

Callable[[], tuple[Array, …]]

Note

Compatible with jax.jit(). Memory scales as O(n_steps * n_sources * n_charges).