Built-in Callbacks¶
Plot on-the-fly¶
- class lambdapic.callback.plot.PlotFields(field_configs: List[Dict], prefix: str | Path, interval: int | float | Callable = 100, figsize: tuple | None = None, dpi: int = 300)[source]¶
Callback to plot and overlay multiple fields with flexible configuration.
Creates plots with specified fields overlaid using transparency cmaps: bwr_alpha, gold_alpha, grey_alpha, red_alpha, blue_alpha, gwb_alpha.
Supports both string-named fields (fetched from simulation) and direct array inputs.
Only rank 0 creates plots in MPI parallel runs.
- Parameters:
field_configs (List[Dict]) – List of field configurations, each specifying: - field: Field name (str) or array (np.ndarray) to plot - scale: Scaling factor (default=1.0), multiplied by the field value - cmap: Matplotlib colormap (default=’viridis’) - vmin: Minimum value for normalization (optional) - vmax: Maximum value for normalization (optional)
prefix (Union[str, Path]) – Output directory for plots
interval (Union[int, float, Callable] = 100) – Save interval
figsize (Tuple[float, float] = (10, 6)) – Figure size
dpi (int = 300) – Image DPI
Example
>>> # Using field names >>> field_configs = [ ... dict(field='rho', scale=-1/e/nc, cmap='Grays', vmin=-1.0, vmax=1.0), ... dict(field='ey', scale=1/4e12, cmap='bwr_alpha', vmin=-1.0, vmax=1.0), ... ]
>>> # Using direct arrays from other callbacks >>> extract_ne = ExtractSpeciesDensity(sim, ele, interval=100) >>> field_configs = [ ... dict(field=extract_ne.density, scale=1/nc, cmap='viridis'), ... dict(field='ey', scale=1/4e12, cmap='bwr') ... ] >>> sim.run(callbacks=[ ... extract_ne, ... PlotFields(field_configs, prefix='plots', interleval=100)])
HDF5¶
Callbacks for saving simulation data to HDF5 format. These allow saving:
Electromagnetic fields
Species densities
Individual particle data
These callbacks perform parallel writes without need for parallel-hdf5, by initializing chunked dataset on rank 0 then performing parallel writes of patches sequentially on each rank.
Both SaveFieldsToHDF5 and SaveSpeciesDensityToHDF5 support an optional slice parameter for np.s_-style subset selection, e.g. slice=np.s_[:, :, 100] or slice=np.s_[::2, ::2, ::5]. SaveFieldsToHDF5 additionally supports an mpi parameter to control MPI collective I/O behavior.
SaveFieldsToHDF5¶
- class lambdapic.callback.hdf5.SaveFieldsToHDF5(prefix: str | Path = '', interval: int | float | Callable = 100, components: List[str] | None = None, mpi: bool = False, slice: tuple[int | slice, ...] | None = None)[source]¶
Callback to save field data to HDF5 files.
Creates a new HDF5 file for each save with name pattern:
prefix/000100.h5
prefix/000200.h5
…
The data structure in each file:
/ex, /ey, /ez (electric fields)
/bx, /by, /bz (magnetic fields)
/jx, /jy, /jz (currents)
/rho (charge density)
- Parameters:
prefix (str) – Prefix for output filenames. For example, if prefix is ‘output’, the files will be named ‘output/t000100.h5’, ‘output/t000200.h5’, etc.
interval (Union[int, float, Callable], optional) – Number of timesteps between saves, or a function(sim) -> bool that determines when to save. Defaults to 100.
components (Optional[List[str]], optional) – List of field components to save. Available: [‘ex’,’ey’,’ez’,’bx’,’by’,’bz’,’jx’,’jy’,’jz’,’rho’]. If None, saves all components.
slice (tuple[int | slice, ...] | None, optional) – Subset of the domain to save, specified via
np.s_indexing (e.g.,slice=np.s_[:, :, 100],slice=np.s_[::2, ::2, ::5],slice=np.s_[500:, :, :]). Accepts anynp.s_-style tuple of ints and/or slices. If None, saves the full domain. Defaults to None.
SaveSpeciesDensityToHDF5¶
- class lambdapic.callback.hdf5.SaveSpeciesDensityToHDF5(species: Species, prefix: str | Path = '', interval: int | float | Callable = 100, mpi: bool = False, slice: tuple[int | slice, ...] | None = None)[source]¶
Callback to save species density data to HDF5 files.
Creates a new HDF5 file for each save with name pattern:
prefix/speciesname_000100.h5
prefix/speciesname_000200.h5
…
The data structure in each file:
/density (2D or 3D array)
- Parameters:
species (Species) – The species whose density will be saved
prefix (str) – Prefix for output filenames. For example, if prefix is ‘output’, the files will be named ‘output/{species.name}_000100.h5’, ‘output/{species.name}_000200.h5’, etc.
interval (Union[int, float, Callable], optional) – Number of timesteps between saves, or a function(sim) -> bool that determines when to save. Defaults to 100.
slice (tuple[int | slice, ...] | None, optional) – Subset of the domain to save, specified via
np.s_indexing (e.g.,slice=np.s_[:, :, 100],slice=np.s_[::2, ::2, ::5],slice=np.s_[500:, :, :]). Accepts anynp.s_-style tuple of ints and/or slices. If None, saves the full domain. Defaults to None.
SaveParticlesToHDF5¶
- class lambdapic.callback.hdf5.SaveParticlesToHDF5(species: Species, prefix: str | Path = '', interval: int | float | Callable = 100, attrs: List[str] | None = None)[source]¶
Callback to save particle data to HDF5 files.
Creates a new HDF5 file for each save with name pattern:
prefix/{species.name}_particles_000100.h5
prefix/{species.name}_particles_000200.h5
…
The data structure in each file:
/id
/x, y (positions)
/w (weights)
/… (other specified attributes)
- Parameters:
species (Species) – The particle species to save
prefix (str) – Prefix for output filenames. For example, if prefix is ‘output’, the files will be named ‘output/{species.name}_particles_0000100.h5’.
interval (Union[int, float, Callable], optional) – Number of timesteps between saves, or a function(sim) -> bool that determines when to save. Defaults to 100.
attrs (Optional[List[str]], optional) – List of particle attributes to save. If None, saves all attributes.
RestartDump¶
Callback that dumps simulation checkpoints using dill pickling. Runs at the "end" stage of each timestep. Checkpoints can be reloaded using RestartDump.load.
- class lambdapic.callback.restart.RestartDump(out_dir: str | Path, interval: int | float | Callable = 1000, keep: int | None = None, dump_signals: list[int] | bool = False)[source]¶
Callback that persists per-rank restart checkpoints for later replay.
The callback runs at stage
"end"and captures one shard per MPI rank insideout_dir/ckpt_<itime>/. Each shard stores the fullSimulationstate so a subsequentRestartDump.load()call can resume execution on the same rank topology.- Parameters:
out_dir (str | Path) – Root directory that will hold checkpoint folders.
interval (int | float | Callable) – Dump cadence; accepts step counts, wall-clock seconds, or a predicate callable that mirrors the base callback interval semantics.
keep (int | None) – Number of most recent checkpoints to retain. When set, rank 0 trims older directories after a successful dump.
dump_signals (Sequence[int] | bool) – POSIX signals that trigger an immediate checkpoint;
TrueregistersSIGINTandSIGTERM,Falsedisables signal-triggered dumps.
- stage¶
Simulation stage where the callback executes.
- Type:
str
Examples
>>> sim = Simulation2D(...) >>> sim.run(callbacks=[RestartDump('checkpoints', interval=100)]) # To restart the simulation, before calling the sim.run # replace the sim instance with the loaded >>> sim = RestartDump.load('checkpoints/ckpt_000100') >>> sim.run(callbacks=...) # Continue from checkpoint
Note
Setting
dump_signalsallows automatic checkpointing when simulation is stopped by time limit of job scheduler like slurm.- static load(ckpt_dir: str | Path, comm=None) Simulation | Simulation3D[source]¶
Load a Simulation from a RestartDump checkpoint directory.
- Parameters:
ckpt_dir (str|Path) – Path to a single checkpoint directory (ckpt_xxxxxx).
comm (mpi4py.MPI.Comm) – Optional MPI communicator to use.
- Returns:
Simulation or Simulation3D instance restored to the checkpoint state.
MovingWindow¶
Callback for implementing a moving window that follows the laser pulse. This maintains high resolution in the region of interest while reducing computational cost by dropping trailing cells.
- class lambdapic.callback.utils.MovingWindow(velocity: float | Callable[[float], float], start_time: float | None = None, inject_particles: bool = True, stop_inject_time: float | None = None)[source]¶
Callback implementing moving window technique along x-direction.
The moving window follows the laser or plasma flow by periodically shifting the simulation domain while maintaining proper boundary conditions.
- Parameters:
velocity (Union[float, Callable[[float], float]]) – Window velocity in m/s. Can be constant or function of time (velocity=f(sim.time))
start_time (Optional[float]) – Time at which to start moving window. Defaults to sim.Lx/c.
inject_particles (bool) – Whether to inject particles in new regions. Defaults to True.
stop_inject_time (Optional[float]) – Time to stop particle injection. Defaults to None.
- stage¶
The simulation stage when this callback is executed.
- Type:
str
- total_shift¶
Total accumulated shift distance.
- Type:
Optional[float]
- patch_this_shift¶
Shift amount within current patch.
- Type:
Optional[float]
- num_shifts¶
Number of shifts performed.
- Type:
int
Note
Handles both forward (positive) and backward (negative) moving windows
Maintains proper particle distributions in new regions
Updates patch neighbor relationships after shifts
Removes PML boundaries when moving starts
Lasers¶
Laser injection callbacks for PIC simulations.
Simple laser¶
Use SimpleLaser2D or SimpleLaser3D. Supports additional parameters for laser positioning and orientation:
y0,z0: laser center position (defaults toLy/2,Lz/2)angle_y,angle_z: incident angle in y and z direction (defaults to 0;angle_zis not implemented and must be 0)cep: carrier envelope phase (default: 0)
- class lambdapic.callback.laser.SimpleLaser(a0: float, w0: float, ctau: float, y0: float | None = None, z0: float | None = None, angle_y: float = 0, angle_z: float = 0, tstop: float | None = None, pol_angle: float = 0.0, cep: float = 0.0, l0: float = 8e-07, side='xmin')[source]¶
A simple laser pulse implementation with basic spatial and temporal profiles. This class provides a straightforward way to inject a laser pulse into the simulation from the left boundary with a Gaussian transverse profile and a smooth temporal envelope.
Use SimpleLaser2D or SimpleLaser3D for 2D and 3D simulations, respectively.
Note
This is a simplified laser implementation suitable for basic simulations. For more accurate physics including proper beam evolution, wavefront curvature, and Gouy phase, use the GaussianLaser class instead.
- Parameters:
sim – Simulation object that this laser will be injected into
a0 – Normalized vector potential amplitude
w0 – Laser waist size
ctau – Pulse duration (c*tau)
y0 – y position of the laser center (default: Ly/2)
z0 – z position of the laser center (default: Lz/2). No effect for 2D laser.
angle_y – incident angle with boundary normal in y direction (default: 0)
angle_z – NOT IMPLEMENTED. Must be 0.
tstop – Time at which the laser pulse should stop (default: 2*ctau)
pol_angle – Polarization angle in radians (default: 0.0 for y-polarization)
cep – Carrier envelope phase (default: 0.0)
l0 – Laser wavelength (default: 800nm)
- Raises:
ValueError – If parameters are invalid (negative or zero values)
- class lambdapic.callback.laser.SimpleLaser2D(a0: float, w0: float, ctau: float, y0: float | None = None, z0: float | None = None, angle_y: float = 0, angle_z: float = 0, tstop: float | None = None, pol_angle: float = 0.0, cep: float = 0.0, l0: float = 8e-07, side='xmin')[source]¶
- Parameters:
sim – Simulation object that this laser will be injected into
a0 – Normalized vector potential amplitude
w0 – Laser waist size
ctau – Pulse duration (c*tau)
y0 – y position of the laser center (default: Ly/2)
z0 – z position of the laser center (default: Lz/2). No effect for 2D laser.
angle_y – incident angle with boundary normal in y direction (default: 0)
angle_z – NOT IMPLEMENTED. Must be 0.
tstop – Time at which the laser pulse should stop (default: 2*ctau)
pol_angle – Polarization angle in radians (default: 0.0 for y-polarization)
cep – Carrier envelope phase (default: 0.0)
l0 – Laser wavelength (default: 800nm)
- Raises:
ValueError – If parameters are invalid (negative or zero values)
- class lambdapic.callback.laser.SimpleLaser3D(a0: float, w0: float, ctau: float, y0: float | None = None, z0: float | None = None, angle_y: float = 0, angle_z: float = 0, tstop: float | None = None, pol_angle: float = 0.0, cep: float = 0.0, l0: float = 8e-07, side='xmin')[source]¶
- Parameters:
sim – Simulation object that this laser will be injected into
a0 – Normalized vector potential amplitude
w0 – Laser waist size
ctau – Pulse duration (c*tau)
y0 – y position of the laser center (default: Ly/2)
z0 – z position of the laser center (default: Lz/2). No effect for 2D laser.
angle_y – incident angle with boundary normal in y direction (default: 0)
angle_z – NOT IMPLEMENTED. Must be 0.
tstop – Time at which the laser pulse should stop (default: 2*ctau)
pol_angle – Polarization angle in radians (default: 0.0 for y-polarization)
cep – Carrier envelope phase (default: 0.0)
l0 – Laser wavelength (default: 800nm)
- Raises:
ValueError – If parameters are invalid (negative or zero values)
Gaussian laser¶
Use GaussianLaser2D or GaussianLaser3D.
Supports Laguerre-Gaussian (LG) beam modes via the l (azimuthal index) and p (number of radial nodes) parameters. When both are zero (the default), a standard Gaussian beam is injected.
- class lambdapic.callback.laser.GaussianLaser(a0: float, l0: float, w0: float, ctau: float, x0: float | None = None, y0: float | None = None, z0: float | None = None, tstop: float | None = None, pol_angle: float = 0.0, cep: float = 0.0, focus_position: float = 0.0, side: str = 'xmin', l: int = 0, p: int = 0)[source]¶
Implementation of a proper Gaussian laser beam with full physics including:
Gaussian temporal and spatial profiles
Proper beam waist evolution (\(w(z) = w_0\sqrt{1 + (z/z_R)^2}\))
Gouy phase (\(tan^{-1}(z/z_R)\))
Wavefront curvature (\(R(z) = z(1 + (z_R/z)^2)\))
Correct phase evolution including propagation and curvature terms
Laguerre-Gaussian (LG) beam modes via
landpparameters
Use GaussianLaser2D or GaussianLaser3D for 2D and 3D simulations, respectively.
Note
This implementation provides more accurate physics than SimpleLaser, including proper beam evolution and phase effects. Use this for realistic simulations where these effects matter.
- Parameters:
a0 – Normalized vector potential amplitude
l0 – Laser wavelength
w0 – Waist size at focus
ctau – Pulse duration (c*tau)
x0 – Pulse center position from boundary (default: 3*ctau)
y0 – y position of the laser center (default: 0)
z0 – z position of the laser center (default: 0). No effect for 2D laser.
tstop – Time to stop injection (default: 6*ctau)
pol_angle – Polarization angle in radians (default: 0.0 for y-polarization)
cep – Carrier envelope phase (default: 0.0)
focus_position – Position of laser focus relative to boundary (default: 0.0)
side – Injection boundary (‘xmin’ or ‘xmax’) (default: ‘xmin’)
l – Azimuthal index of Laguerre-Gaussian laser (default: 0)
p – Number of radial nodes of Laguerre-Gaussian laser (default: 0)
- class lambdapic.callback.laser.GaussianLaser2D(a0: float, l0: float, w0: float, ctau: float, x0: float | None = None, y0: float | None = None, z0: float | None = None, tstop: float | None = None, pol_angle: float = 0.0, cep: float = 0.0, focus_position: float = 0.0, side: str = 'xmin', l: int = 0, p: int = 0)[source]¶
- Parameters:
a0 – Normalized vector potential amplitude
l0 – Laser wavelength
w0 – Waist size at focus
ctau – Pulse duration (c*tau)
x0 – Pulse center position from boundary (default: 3*ctau)
y0 – y position of the laser center (default: 0)
z0 – z position of the laser center (default: 0). No effect for 2D laser.
tstop – Time to stop injection (default: 6*ctau)
pol_angle – Polarization angle in radians (default: 0.0 for y-polarization)
cep – Carrier envelope phase (default: 0.0)
focus_position – Position of laser focus relative to boundary (default: 0.0)
side – Injection boundary (‘xmin’ or ‘xmax’) (default: ‘xmin’)
l – Azimuthal index of Laguerre-Gaussian laser (default: 0)
p – Number of radial nodes of Laguerre-Gaussian laser (default: 0)
- class lambdapic.callback.laser.GaussianLaser3D(a0: float, l0: float, w0: float, ctau: float, x0: float | None = None, y0: float | None = None, z0: float | None = None, tstop: float | None = None, pol_angle: float = 0.0, cep: float = 0.0, focus_position: float = 0.0, side: str = 'xmin', l: int = 0, p: int = 0)[source]¶
- Parameters:
a0 – Normalized vector potential amplitude
l0 – Laser wavelength
w0 – Waist size at focus
ctau – Pulse duration (c*tau)
x0 – Pulse center position from boundary (default: 3*ctau)
y0 – y position of the laser center (default: 0)
z0 – z position of the laser center (default: 0). No effect for 2D laser.
tstop – Time to stop injection (default: 6*ctau)
pol_angle – Polarization angle in radians (default: 0.0 for y-polarization)
cep – Carrier envelope phase (default: 0.0)
focus_position – Position of laser focus relative to boundary (default: 0.0)
side – Injection boundary (‘xmin’ or ‘xmax’) (default: ‘xmin’)
l – Azimuthal index of Laguerre-Gaussian laser (default: 0)
p – Number of radial nodes of Laguerre-Gaussian laser (default: 0)
Combining lasers¶
Lasers can be combined using the + operator to inject multiple lasers in a single callback:
combined = laser1 + laser2
Both lasers must be from the same side and the same dimension (2D or 3D). The resulting combined laser behaves as a single callback that injects all constituent lasers.
Utility callbacks¶
SetTemperature¶
Set the temperature of a species to a given value in eV.
- class lambdapic.callback.utils.SetTemperature(species: Species, temperature: float | int | List[float | int], interval: int | float | Callable | None = None)[source]¶
Callback to set the particle momenta (ux, uy, uz) for a species to a relativistic Maxwell-Jüttner distribution with the specified temperature (in units of eV).
- Parameters:
species (Species) – The target species whose temperature is to be set.
temperature (float) – Temperature in units of eV.
interval (int or callable) – Frequency (in timesteps) or callable(sim) for when to apply, defaults to run at the first timestep only once.
ExtractSpeciesDensity¶
Extract the density of a species to buffer. Supports an optional slice parameter for np.s_-style subset selection.
- class lambdapic.callback.utils.ExtractSpeciesDensity(sim: Simulation, species: Species, interval: int | float | Callable = 100, slice: tuple[int | slice, ...] | None = None)[source]¶
Callback to extract species density from all patches.
Only rank 0 will gather the data, other ranks will get zeros.
- Parameters:
sim (Simulation) – Simulation instance.
species (Species) – Species instance to extract density from.
interval (Union[int, float, Callable], optional) – Number of timesteps between saves, or a function(sim) -> bool that determines when to save. Defaults to 100.
Example
>>> ne_ele = ExtractSpeciesDensity(sim, ele, interval=100) use in PlotFields: >>> sim.run(1000, callbacks[ ne_ele, PlotFields( [dict(field=ne_ele.density, scale=1/nc, cmap='Grays', vmin=0, vmax=20), dict(field='ey', scale=e/(m_e*c*omega0), cmap='bwr_alpha', vmin=-laser.a0, vmax=laser.a0) ], prefix='laser-target'), ])
Note
This callback collects data from all patches and sends it to rank 0. This could be expensive for 3D simulations. Use with caution. If you want to save the density to file, use
SaveSpeciesDensityToHDF5instead.
LoadParticles¶
Load particles from a hdf5 file.
- class lambdapic.callback.utils.LoadParticles(species: Species, file: str | Path, interval: int | float | Callable | None = None)[source]¶
Callback to load particles from HDF5 files with batch processing support.
The file should at least contains:
‘/x’
‘/y’
‘/z’, for 3d
‘/w’
Other attributes supported by the target particle class will be loaded if present.
You can load from a file generated by
SaveParticlesToHDF5.- Parameters:
species (Species) – The target species to load particles into.
file (str|Path) – Path to the HDF5 file containing particle data.
interval (Union[int, float, Callable], optional) – Frequency of execution. Can be a number of timesteps, a time interval, or a callable function that returns True when the callback should execute. Defaults to running only at the first timestep.
- _batch_size¶
Number of particles to process in each batch. Controls memory usage during loading. Default is 10,000 particles per batch.
- Type:
int
Example
>>> # Load electrons from an HDF5 file after simulation initialization >>> load_ele = LoadParticles(ele, "particles.h5") >>> sim.run(1000, callbacks=[load_ele])
Note
The HDF5 file should contain datasets for all particle attributes (x, y, z, ux, uy, uz, w, etc.)
Particles are automatically distributed to patches based on their spatial coordinates
Batch processing reduces memory usage for large particle datasets