Cavity Class
The public Cavity class is an OpticElement wrapper around CavityAtom, which inherits from Element. It represents a standing-wave RF cavity with accelerating voltage, RF phase, and optional upstream and downstream coupler kicks.
In this page we focus on the first-order matrix and on how the cavity-specific tracking path is implemented in OCELOT.
Cavity in the Element Architecture
Cavity is an edge-aware RF family:
- public wrapper:
Cavity - atom:
CavityAtom - always-available optics path: first-order
TransferMap - default active tracking transformation:
CavityTM supported_tms = {CavityTM}has_edge = True, so the element is represented byENTRANCE -> MAIN -> EXIT
For Cavity, the entrance and exit maps are not geometric pole-face edges as in a bend. They are used for optional coupler-kick matrices and offsets. If coupler coefficients are zero, these edge maps reduce to identity maps.
Class Definition Snippet
from ocelot.cpbd.elements import Cavity
cav = Cavity(l=1.0, v=0.02, phi=0.0, freq=1.3e9)
# full parameter list:
# Cavity(l=0.0, v=0.0, phi=0.0, freq=0.0,
# vx_up=0, vy_up=0, vxx_up=0, vxy_up=0,
# vx_down=0, vy_down=0, vxx_down=0, vxy_down=0,
# eid=None, tm=None)
The wrapper also provides:
cav.remove_coupler_kick()
which resets all upstream and downstream coupler coefficients to zero.
Parameters
l(float): cavity length [m]v(float): total RF voltage [GV]phi(float): RF phase [deg]freq(float): RF frequency [Hz]vx_up,vy_up(complexorfloat): zero-order upstream coupler-kick coefficientsvxx_up,vxy_up(complexorfloat): first-order upstream coupler coefficientsvx_down,vy_down(complexorfloat): zero-order downstream coupler-kick coefficientsvxx_down,vxy_down(complexorfloat): first-order downstream coupler coefficientseid(str, optional): element identifier
With the current OCELOT convention,
phi = 0gives maximum accelerating voltagephi = 90^\circis the zero-crossing case
because the reference energy gain is computed as
First-Order Main Matrix
The cavity body matrix is computed in CavityAtom._R_main_matrix(...). For a slice of length z, OCELOT uses the slice voltage
and then builds a first-order matrix of the form
The transverse blocks are identical in x and y, which reflects the symmetric RF focusing model used here.
OCELOT defines
with
and
Then the transverse coefficients are
For the longitudinal block, OCELOT computes
with
and
In the general RF case, the code uses
At zero crossing, where the code detects both vanishing energy gain and , it switches to the analytic limit
This is exactly the branch structure implemented in CavityAtom._R_main_matrix(...).
If v = 0, the code falls back to the drift-like uni_matrix(...) result.
Coupler Entrance and Exit Maps
If coupler coefficients are present, CavityAtom builds additional entrance and exit maps. The first-order coupler matrix is
with
and the corresponding additive kick vector is
The entrance map uses the upstream coefficients and the exit map uses the downstream coefficients.
How OCELOT Implements It
The cavity has two related paths:
Cavity
-> CavityAtom
-> create_first_order_*_params(...)
-> FirstOrderParams
-> TransferMap # first_order_tms, R(), Twiss
Cavity
-> CavityAtom
-> create_cavity_tm_*_params(...)
-> CavityParams
-> CavityTM # active tracking path
First-order optics path
For R() and linear optics, CavityAtom provides:
create_first_order_main_params(...)create_first_order_entrance_params(...)create_first_order_exit_params(...)
These return FirstOrderParams, so the wrapper can keep the usual TransferMap-based optics path.
Active cavity tracking path
For actual tracking, the wrapper uses CavityTM. The atom therefore also implements:
create_cavity_tm_main_params(...)create_cavity_tm_entrance_params(...)create_cavity_tm_exit_params(...)
These methods package the same linear R, B, and tilt data together with v, freq, and phi into CavityParams.
CavityTM then:
- uses the linear
R/Bmap fromCavityParams - applies reference-energy change through
create_delta_e(...) - adds the cavity-specific longitudinal RF update in
map4cav(...)for theMAINmap
For ENTRANCE and EXIT, CavityTM behaves like a linear first-order map, which is exactly what is needed for the coupler-kick pieces.
Example of Use
For an element with has_edge=True, R() returns the full sequence [entrance, main, exit]:
import numpy as np
from ocelot.cpbd.elements import Cavity
cav = Cavity(l=1.0, v=0.02, phi=0.0, freq=1.3e9)
np.set_printoptions(precision=4, suppress=True)
print(cav.R(energy=0.15)) # [GeV]
[array([[1., 0., 0., 0., 0., 0.],
[0., 1., 0., 0., 0., 0.],
[0., 0., 1., 0., 0., 0.],
[0., 0., 0., 1., 0., 0.],
[0., 0., 0., 0., 1., 0.],
[0., 0., 0., 0., 0., 1.]]),
array([[ 0.9365, 0.9384, 0. , 0. , 0. , 0. ],
[-0.0055, 0.9367, 0. , 0. , 0. , 0. ],
[ 0. , 0. , 0.9365, 0.9384, 0. , 0. ],
[ 0. , 0. , -0.0055, 0.9367, 0. , 0. ],
[ 0. , 0. , 0. , 0. , 1. , -0. ],
[ 0. , 0. , 0. , 0. , 0. , 0.8824]]),
array([[1., 0., 0., 0., 0., 0.],
[0., 1., 0., 0., 0., 0.],
[0., 0., 1., 0., 0., 0.],
[0., 0., 0., 1., 0., 0.],
[0., 0., 0., 0., 1., 0.],
[0., 0., 0., 0., 0., 1.]])]
In this example the entrance and exit maps are identity matrices because no coupler coefficients were provided.