Particle motion: trajectories, invariants and animation

Compute once, select physical time

import numpy as np
import vaft.diagram as diagram
from vaft.process.particle import particle_motion_case
from vaft.plot import ParticleOrbitView, particle_overview

comparison = particle_motion_case("magnetic_mirror")
end = min(comparison.full.time[-1], comparison.guiding_center.time[-1])
times = np.linspace(0, end, 24)

# The scalar and animated calls select the same scientific state.
static = diagram.magnetic_mirror(trajectory=comparison, time=times[5])
movie = diagram.magnetic_mirror(
    trajectory=comparison, time=times, animation=True, fps=8
)
movie.save("mirror.gif")

s = np.linspace(-9.99, 9.99, 200)
view = ParticleOrbitView.from_comparison(
    comparison, bounce_coordinate=lambda x: x[2],
    well_coordinate=s, well_B=1 + (s / 10)**2,
)
fig, axes = particle_overview(view, time=times[5])
panels = particle_overview(view, time=times, animation=True, fps=8)

The mirror’s B(s) is stationary. Its marker, trajectory, velocity, energy partitions and invariant histories use the same physical timestamp. The renderer never re-integrates or recomputes diagnostics in a frame. Display-time interpolation is linear, recorded, and cannot extrapolate. The native Boris and adaptive GC sample times are retained independently of playback fps.

Supported experiments

particle_motion_case supports gyration, exb_drift, grad_b_drift, curvature_drift, toroidal_drift, magnetic_mirror, mirror_passing, tokamak_trapped, tokamak_passing and symmetry_breaking. Use charge=-1 to reverse charge-sensitive motion. Set aspect_ratio=1.5 for a qualified spherical-tokamak geometry reference; large-aspect-ratio banana scalings do not become accurate merely because that case can be integrated.

Default examples use an illustrative SI particle, q=1 C and m=1 kg. Resolved parameters are recorded. They are not electron/ion mass-ratio examples. speed, pitch_angle (radians), duration (seconds) and dt can be supplied. The benchmark helper rejects an initial abs(Omega_c)*dt > 0.3; inspect the maximum over the full orbit too and refine the step to establish accuracy.

The existing exb_drift, curvature_drift, toroidal_drift, guiding_center_invariants, canonical_toroidal_momentum, trapped_and_passing_orbits, toroidal_symmetry_breaking, ripple_well_formation and stochastic_ripple_orbit accept a computed trajectory, scalar/sequence time, and animation=True. Their historical calls without these controls keep their original static scenes. The computed extension shows one physical particle and its independently integrated GC; the historical two-species mass-ratio and schematic phase parameters belong to the static references. A replay through stochastic_ripple_orbit explicitly labels stochasticity as unestablished.

Reference animations

Cartesian gyration Static magnetic mirror
Gyration Mirror bounce

The artifact manifest links all six families to animations and quantitative panels, and all but the tokamak and symmetry-breaking families to static SVGs. The mirror and invariants families share one experiment and so one panel image. The manifest also records the commit it was generated on and a SHA-256 of every scientific source its numbers depend on; the documentation catalog gate refuses a manifest whose sources have changed, and python -m workflow.particle_motion.run --check re-traces the six examples. Some manifest diagnostics are not meaningful for every family. orbit_class is no_resolved_turn for the cartesian and full-gc runs, which have no turning point to classify. gc_P_phi_residual_max is large for symmetry-breaking, because a 3-D field does not conserve P_phi; it is not a numerical error.

Physics and numerical contracts

vaft.data.particle.ParticleField uses right-handed Cartesian SI coordinates. A Jacobian has J[i,j] = dB_i/dx_j. Analytic derivatives are preferred; numerical derivatives require an explicit step and an h/h2 audit. An electrostatic field requires a consistent potential; potential gradients are checked. Domain queries precede field evaluation, including derivative probes.

vaft.process.particle exposes trace_particle_orbit, trace_guiding_center, particle_to_guiding_center, analyze_particle_orbit and compare_particle_orbits. The GC state is (X, p_parallel, mu) with mu held constant. The equations use B*=B+(p_parallel/q) curl(b) and the Hamiltonian H=p_parallel**2/(2m)+mu*B+q*Phi. DOP853 integrates scaled dimensionless states; position/momentum scales, tolerances and accepted times are recorded. It is not a symplectic method and has no long-time conservation guarantee.

GC validity requires magnetization and weak electric drift. Diagnostics report rho/L_B, parallel-curvature ordering, E×B speed/particle speed, and numerical steps relative to gyroperiod. The 0.1 educational warning threshold is recorded and is not a universal validity boundary. Full-orbit magnetic moment is an instantaneous drift-frame estimate; fixed GC mu is a model assumption. The initial particle/GC conversion is leading order and is not a first-order Lie transform. Comparison metadata distinguishes local-center subtraction from a centered one-gyroperiod time-window average with incomplete edges omitted.

Energy residuals use a kinetic/potential-variation scale. Canonical momentum residuals use mechanical/field contribution scales, preserving meaningful normalization even when the total initially vanishes. Canonical momentum uses an explicitly specified vector-potential gauge; the 3D example never substitutes an axisymmetric flux relation. Periods and toroidal precession are reported from completed bounce/transit intervals, with unwrapped angles.

Bounce action is defined only with a supplied signed periodic field-line arc coordinate. Incomplete cycles, unresolved closure and incorrect arc velocity are reported rather than assigned an action. The on-axis parabolic mirror has an exact harmonic period and action benchmark. Its field is exactly solenoidal and current-carrying; it is not an assumed vacuum-coil solution.

vaft.process.particle_fields provides uniform, slab, mirror and curl-defined toroidal/3D reference fields. equilibrium_particle_field reuses VAFT’s COCOS-aware equilibrium interpolator, preserving its documented F-edge clipping; its map is not extrapolated. filament_particle_field reuses the existing midpoint-rule Biot–Savart calculation and provides a vector potential with the same quadrature, plus a conductor exclusion region.

A trace returns its valid accepted prefix with an explicit reason for domain exit, field null, nonfinite field/state, unresolved derivatives, GC singularity, or integration failure. Initial data errors raise exceptions. Boundary termination is not a computed wall-impact location. At valid boundary samples, local energy and center diagnostics remain available even when the derivative stencil would cross the domain: derivative diagnostics are NaN, with a stencil_outside_domain audit. Comparison records incomplete derivative coverage and raises its ordering warning rather than certifying an unavailable estimate.

Steps smaller than the floating-point spacing of absolute timestamps are input errors. Shift t0 toward zero for short gyro-resolving intervals at a large time origin. Full-orbit updates advance by the represented timestamp interval.

Both diagram and diagnostic animation sidecars include full_orbit and guiding_center provenance records: charge, mass, initial state, field source, termination, integration method and solver settings. These records also cover custom comparisons created directly with the tracing APIs. Uniform-field provenance includes the supplied Cartesian B and E vectors. Straight background field lines follow the supplied uniform-field direction; arbitrary field geometries retain the sampled field arrow without invented straight lines.

Reproduction and limits

Run python -m workflow.particle_motion.run from the source root to generate six reference families, their GIFs, diagnostic panels, static SVGs (all but the tokamak and symmetry-breaking families) and artifact manifest under docs/assets/particle-motion/. Physical tests are in test/test_process_particle.py; replay tests are in test/test_particle_animation.py.

This implements the static-field portion of issues #2003–#2009. The slowly changing mirror experiment required by #2007 remains deferred, along with inductive/time-dependent fields, collisions, transport and external-solver cross-validation. The 3D reference is a controlled vacuum harmonic, not a calculated plasma response. Canonical-momentum change alone supports no claim of secular transport, stochasticity or NTV torque.

results matching ""

    No results matching ""