Element Architecture in OCELOT
The CPBD element system is layered. A logical beamline element is usually split into a public wrapper, an internal atom, a TMParams container, and a transformation. This separation keeps the public API stable while allowing each element family to choose the most suitable tracking algorithm.
Four Layers
| Layer | Typical files | Responsibility |
|---|---|---|
| Public wrapper | elements/quadrupole.py, elements/cavity.py | User-facing API, cached maps, active TM selection, section slicing |
| Atom | elements/quadrupole_atom.py, elements/cavity_atom.py | Physics state and create_*_params(...) hook methods |
TMParams | tm_params/first_order_params.py, tm_params/cavity_params.py | Typed data contract between atom and transformation |
| Transformation | transformations/transfer_map.py, transformations/cavity.py | Runtime algorithm that applies the map to particles |
The public element object that a lattice usually stores is the wrapper, most often an OpticElement subclass.
Runtime Flow
When a lattice updates or rebuilds maps, the call chain is usually:
MagneticLattice.update_transfer_maps()
-> element.set_tm(...)
-> OpticElement._create_tms(...)
-> Transformation.from_element(...)
-> atom.create_*_params(...)
-> TMParams
-> Transformation.map_function(...)
The wrapper decides which transformation family should be active. The atom computes the parameter object for the requested energy. The transformation uses that parameter object to update particle coordinates.
Two Transformation Roles
One of the most important ideas in the current architecture is that OCELOT keeps two map paths separate.
First-order optics path
first_order_tms is the always-available first-order path. It is built with TransferMap and is used by linear optics routines such as Twiss calculations.
This means that even an element family with a custom active tracking method still keeps a linear optics representation.
Active tracking path
tms is the active tracking path. It may use a different transformation family, for example:
Quadrupole:TransferMap,SecondTM, orKickTMCavity:CavityTMMultipole:MultipoleTM
So a family can keep a first-order optics path for R() and Twiss calculations while using another transformation for actual particle tracking.
Wrapper Contract Versus Atom Hook Surface
One subtle but important point is that the wrapper contract and the atom hook surface are not the same thing.
supported_tmslists wrapper-selectable active tracking methods- the atom may still implement a broader hook surface than the wrapper exposes
first_order_tmsis a separate always-available optics path and should not be confused withsupported_tms
For example, Cavity keeps a first-order TransferMap path for optics and R(), but its active wrapper contract is still only CavityTM.
Edge-aware Elements
The atom attribute has_edge controls how a wrapper builds its map sequence.
has_edge = False: only oneMAINmap is created.has_edge = True: the wrapper buildsENTRANCE -> MAIN -> EXIT.
This rule applies both to the always-available first-order optics path and to the active tracking path.
Because first_order_tms is always built with TransferMap, an edge-aware family must always provide first-order entrance, main, and exit hooks, even if active tracking uses a different transformation such as CavityTM.
For slices created with get_section_tms(...), the current behavior is:
- if
start_l == 0, the entrance map is included - if
start_l + delta_l == l, the exit map is included - a middle slice rebuilds only the main map for the requested length
ignore_edges=Truesuppresses entrance and exit maps explicitly
Representative Examples
Quadrupole
- public wrapper:
Quadrupole - atom:
QuadrupoleAtom, derived fromMagnet - optics path: first-order
TransferMap - active tracking:
TransferMap,SecondTM, orKickTM
This is a good reference family for the standard no-edge wrapper/atom contract.
Cavity
- public wrapper:
Cavity - atom:
CavityAtom - optics path: first-order
TransferMap - active tracking:
CavityTM - edge behavior:
ENTRANCE -> MAIN -> EXIT
Cavity is a good example of a family where the optics path and the active tracking method are intentionally different.
Why the Split Is Useful
- Physics formulas live on atoms, while tracking algorithms live in transformations.
- The same element family can support several active tracking methods.
- First-order optics remain available even when active tracking uses another transformation.
- The wrapper keeps the historical user-facing API stable across lattices and tracking code.
Read Next
OpticElement: the public wrapper- How to Create a New Element
- How to Create a New TM
TMParams: parameter containers between atoms and transformationsElement: minimal atom-layer base classMagnet: atom-layer base class for magnetic families