essos.boozer

Fast guiding-centre tracing in Boozer coordinates, with optional collisions.

BoozerField holds a Boozer spectrum of |B| (cos(m theta - n zeta) modes from booz_xform / booz_xform_jax) with cubic splines in r = sqrt(s) and the profiles iota, G and I with cubic splines in s. For m >= 1 the spline holds b_mn / r, so |B| is regular at the magnetic axis.

trace_boozer() integrates the guiding-centre equations of White (2014) in the K = 0 Boozer form used by SIMSOPT (GuidingCenterNoKBoozerRHS), in the chart (u, w) = sqrt(s) (cos theta, sin theta), which is regular on the axis, with fixed-step RK4 under vmap. A particle is lost when it reaches s = 1. With species (an essos.background_species.BackgroundSpecies whose profiles are given on s) a Monte Carlo collision operator (pitch-angle scattering, slowing down and energy diffusion, Ito Euler-Maruyama, Boozer & Kuo-Petravic, J. Comput. Phys. 1981) acts after every orbit step; a particle whose energy falls below thermal_cutoff times the local temperature of species 0 is thermalised and stops, counted as confined.

Classes

BoozerField

|B| spectrum and iota, G, I profiles in Boozer coordinates.

BoozerTrace

Result of trace_boozer() (NumPy arrays).

Functions

_spline(x, y)

_evaluate(knots, coef, x)

Value and derivative of a piecewise cubic (end pieces extrapolate).

_chart(y)

guiding_center_rhs(field, y, mu, mass, charge)

Time derivative of (u, w, zeta, v_par); mu = v_perp^2 / (2 |B|).

_collision_rates(species, mass, charge, v, point)

collision_kick(species, mass, charge, v, pitch, point, ...)

One Ito Euler-Maruyama step of the Lorentz and energy-scattering operator.

trace_boozer(field, s, theta, zeta, pitch, *, speed, ...)

Trace guiding centres from Boozer (s, theta, zeta) with pitch v_par/v.

Module Contents

essos.boozer._spline(x, y)
essos.boozer._evaluate(knots, coef, x)

Value and derivative of a piecewise cubic (end pieces extrapolate).

class essos.boozer.BoozerField

Bases: equinox.Module

|B| spectrum and iota, G, I profiles in Boozer coordinates.

r_knots: jax.Array
b_coef: jax.Array
s_knots: jax.Array
profile_coef: jax.Array
xm: jax.Array
xn: jax.Array
psi0: float
nfp: int
classmethod from_booz(s, bmnc, xm, xn, iota, G, I, psi0, nfp, mode_tolerance=1e-06)

Build from half-mesh Boozer tables.

bmnc is (modes, len(s)) as written by booz_xform; xn includes the nfp factor; psi0 is the toroidal flux at the boundary over 2 pi. Modes whose amplitude never exceeds mode_tolerance times the largest amplitude are dropped.

classmethod from_booz_xform(booz, psi0, mode_tolerance=1e-06)

Build from a run Booz_xform object (every surface computed).

profiles(s)

(iota, G, I) and their s derivatives.

modB_derivatives(r, theta, zeta)

|B|, d|B|/dr, (d|B|/dtheta)/r and d|B|/dzeta.

modB(s, theta, zeta)
essos.boozer._chart(y)
essos.boozer.guiding_center_rhs(field, y, mu, mass, charge)

Time derivative of (u, w, zeta, v_par); mu = v_perp^2 / (2 |B|).

essos.boozer._collision_rates(species, mass, charge, v, point)
essos.boozer.collision_kick(species, mass, charge, v, pitch, point, dt, noise)

One Ito Euler-Maruyama step of the Lorentz and energy-scattering operator.

dv = (-nu_s v + v^-2 d(v^2 D)/dv) dt + sqrt(2 D dt) xi_1 with D = v^2 nu_par / 2, and dlambda = -lambda nu_D dt + sqrt((1 - lambda^2) nu_D dt) xi_2.

class essos.boozer.BoozerTrace

Result of trace_boozer() (NumPy arrays).

states is (particles, n_save, 5): s, theta, zeta, v_par and the speed v, held at the loss or thermalisation point afterwards. loss_times is -1 for particles that were not lost; thermalized_times likewise.

times: numpy.ndarray
states: numpy.ndarray
loss_times: numpy.ndarray
thermalized_times: numpy.ndarray
energy_error: numpy.ndarray
property lost
loss_fractions()

Cumulative lost fraction at each saved time.

essos.boozer.trace_boozer(field, s, theta, zeta, pitch, *, speed, mass, charge, tmax, timestep, n_save=100, species=None, seed=0, thermal_cutoff=1.5, devices=None, progress=None)

Trace guiding centres from Boozer (s, theta, zeta) with pitch v_par/v.

The step is shortened so that a whole number of steps fits between the n_save saved times (t = 0 included). Particles are sharded over devices (default: every local device).

progress, if given, is called as progress(done, total) in saved intervals: the horizon then runs as up to ten host-side chunks of the same compiled program, with the whole state carried between them, so the orbits are those of an unchunked trace.