How to Create Your Own Physics Process
Ocelot provides a flexible interface to define and implement custom physics processes by extending the base class PhysProc. This allows you to simulate effects such as wakefields, CSR, space charge, or any other custom modification during beam tracking.
Base Class: PhysProc
All physics processes should inherit from the PhysProc class. Here's an overview of its interface and behavior:
Key Methods:
apply(self, p_array, dz)— required. This method is called on every simulation step to apply your custom logic to theParticleArray.prepare(self, lat)(optional) — called once when the process is added to theNavigator. By default, it checks thatstepis an integer. Override it if you need to precompute data (e.g., CSR trajectory).finalize(self, *args, **kwargs)(optional) — called at the end of tracking. You can override it to save computed data or perform cleanup (e.g. in Beam Analysis).
Key Attributes (set automatically by Navigator.add_physics_proc()):
step: how often to apply the process (in units ofNavigator.unit_step)energy: beam energy, can be set manually if neededindx0,indx1: indices of the start and stop elements inlattice.sequences_start,s_stop: start and stop positions along the latticez0: current longitudinal position during tracking (set just beforeapply()is called)
Step Validation
The method check_step() ensures that step is an integer. This is called automatically in the default prepare() implementation:
if not (self.step * 1.).is_integer():
raise ValueError("step must be an integer number")
Minimal Example:
from ocelot import PhysProc
class MyProcess(PhysProc):
def apply(self, p_array, dz):
# Modify the particle array during tracking
pass
Extended Example with prepare and finalize:
class MyProcess(PhysProc):
def prepare(self, lat):
super().prepare(lat)
# Setup or trajectory pre-calculation
def apply(self, p_array, dz):
# Main tracking logic
pass
def finalize(self, *args, **kwargs):
# Save data or diagnostics
pass
To use your process:
proc = MyProcess()
navi = Navigator(lattice)
navi.add_physics_proc(proc, start_element, stop_element)
✅ Quick Guidelines
- Inherit from
PhysProc - Implement
apply()— it is mandatory - Use
prepare()if you need to initialize anything before tracking- Example: CSR physics process calculates the beam trajectory in
prepare()
- Example: CSR physics process calculates the beam trajectory in
- Use
finalize()to store or analyze data after tracking- Example: Beam Analysis stores statistics in
finalize()
- Example: Beam Analysis stores statistics in
- Use attributes like
z0,energy,s_startduring tracking for reference
🔗 Full Tutorial
A complete working example is provided in the tutorial:
👉 Laser Heater Physics Process Tutorial
This tutorial demonstrates how to:
- Implement and register a custom process
- Modify the beam distribution
- Track effects over specific sections of a lattice
If you have questions or want to contribute your own physics models, feel free to open a pull request or start a discussion!