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 any np.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 any np.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 inside out_dir/ckpt_<itime>/. Each shard stores the full Simulation state so a subsequent RestartDump.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; True registers SIGINT and SIGTERM, False disables 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_signals allows 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 to Ly/2, Lz/2)

  • angle_y, angle_z: incident angle in y and z direction (defaults to 0; angle_z is 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 l and p parameters

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 SaveSpeciesDensityToHDF5 instead.

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