Particle Tracks¶
This guide covers how to work with particle track data in dhybridrpy.
Overview¶
Particle tracks record the trajectory of individual particles throughout the simulation.
Getting Started¶
List Available Track IDs¶
from dhybridrpy import DHybridrpy
dpy = DHybridrpy(
input_file="path/to/input",
output_folder="path/to/Output"
)
# Get array of all track IDs for species 1 (default)
track_ids = dpy.tracks()
print(f"Found {len(track_ids)} tracks")
print(track_ids[:5]) # e.g., ['0-1', '0-2', '0-3', '0-4', '0-5']
Track IDs are in the format 'rank-tag' where rank is the MPI rank and tag is the particle's unique identifier.
Access a Single Track¶
# Get the first track
track_id = dpy.tracks()[0]
track = dpy.track(track_id)
# Or directly by ID
track = dpy.track('0-1465')
Track Properties¶
Each track provides position, velocity, field, and other data over time. The suffixes 1, 2, 3 correspond to x, y, z directions:
track = dpy.track(track_id)
# Position components
x = track.x1 # x coordinate
y = track.x2 # y coordinate
# Velocity components
vx = track.v1 # x velocity
vy = track.v2 # y velocity
vz = track.v3 # z velocity
# Electromagnetic fields at particle position
Bx = track.B1 # x magnetic field
By = track.B2 # y magnetic field
Bz = track.B3 # z magnetic field
Ex = track.E1 # x electric field
# Time and iteration info
t = track.t # simulation time
n = track.n # iteration numbers (e.g., [10, 20, 30, ...])
# Energy and charge
ene = track.ene # particle energy
q = track.q # particle charge
All properties return NumPy arrays with one value per stored iteration.
Iterating Over Tracks¶
Using Track IDs¶
For bulk operations, use tracks() to get an array of track IDs and iterate:
# Iterate over all tracks
for track_id in dpy.tracks():
track = dpy.track(track_id)
print(f"Track {track.track_id}: final x = {track.x1[-1]:.2f}")
# Get total number of tracks
n_tracks = len(dpy.tracks())
print(f"Total: {n_tracks} tracks")
Filtering Tracks¶
Use list comprehensions to filter tracks by criteria:
# Find tracks that reached x > 100
far_tracks = [dpy.track(tid) for tid in dpy.tracks() if dpy.track(tid).x1[-1] > 100]
# Find most energetic particle at end of simulation
import numpy as np
def final_speed(track):
return np.sqrt(track.v1[-1]**2 + track.v2[-1]**2 + track.v3[-1]**2)
tracks = [dpy.track(tid) for tid in dpy.tracks()]
fastest_track = max(tracks, key=final_speed)
print(f"Fastest: {fastest_track.track_id}")
Working with Multiple Species¶
If your simulation tracks multiple species, specify the species number:
# Get tracks for species 2
track_ids_sp2 = dpy.tracks(species=2)
track = dpy.track('0-100', species=2)
# Iterate over species 2 tracks
for track_id in dpy.tracks(species=2):
track = dpy.track(track_id, species=2)
print(track.track_id)
Plotting Trajectories¶
Basic Trajectory Plot¶
import matplotlib.pyplot as plt
track = dpy.track(dpy.tracks()[0])
plt.figure(figsize=(10, 6))
plt.plot(track.x1, track.x2)
plt.xlabel('$x/d_i$')
plt.ylabel('$y/d_i$')
plt.title(f'Particle Trajectory: {track.track_id}')
plt.show()
Trajectory with Time Coloring¶
import matplotlib.pyplot as plt
import numpy as np
track = dpy.track(dpy.tracks()[0])
plt.figure(figsize=(10, 6))
scatter = plt.scatter(track.x1, track.x2, c=track.t, cmap='viridis', s=1)
plt.colorbar(scatter, label='$t \\omega_{ci}$')
plt.xlabel('$x/d_i$')
plt.ylabel('$y/d_i$')
plt.title('Particle Trajectory Colored by Time')
plt.show()
Use Lazy Loading for Large Datasets¶
Enable lazy loading to defer data loading until needed: