Skip to content
Riccardo De Maria edited this page Jan 31, 2018 · 2 revisions

Tracking equations

Constants: $$q, m, \beta_0, P_0, E_0$$

Variables: $$\begin{aligned} x& & p_x& =P_x/P_0 \ y& & p_y&=P_y/P_0 \ \sigma& =s - \beta_0 c t & p_\sigma &=\frac{\Delta E}{\beta_0 P_0c} \end{aligned}$$ Extra variables: $$\begin{aligned} \delta&=P/P_0 -1 & r_p&= P_0/P\qquad r_v= \beta_0/\beta \end{aligned}$$

RF Cavity: $$ \frac{\Delta E}{\beta_0 P_0 c} = \frac{V}{\beta_0 P_0 c} \sin (2 \pi f \sigma/\beta_0) \qquad P = \sqrt{E^2 - m^2} \qquad r_p= P_0/P\qquad r_v = \beta_0 E/P\qquad \delta= 1/r_p-1 $$

Drift $$\begin{aligned} \Delta (x,y) &= L \left(p_x, p_y\right) r_p \ \Delta \sigma &= L \left( 1 - r_v \left( 1 +\frac{p_x^2 + p_y^2}{ 2}\right) \right) \end{aligned}$$

Drift exact: $$\begin{aligned} p_z&=\sqrt{(1+\delta)^2-p_x^2-p_y^2} & \beta_z&=\frac{P_0 p_z}{E} \ \Delta (x,y) &= L \frac{\left(p_x,p_y\right)}{p_z} & \Delta \sigma &= L \left( 1 - \frac{\beta_0}{\beta_z} \right) \end{aligned}$$

Multipole: $$ \Delta (p_x + i p_y) = q \sum_n (k_n + i \bar k_n) (x + i y)^n $$

Thin dipole full: $$ \Delta p_x = L \left(h/r_p - q k_1 (1+ h x) \right)\qquad \Delta \sigma = - L h r_v $$

Thin dipole : $$ \Delta p_x = L \left(h \delta - h^2 x \right)\qquad \Delta \sigma = - L h r_v $$

Useful formulas

$$\begin{aligned} \delta&=\frac{P-P_0}{P_0} & p_t&=\frac{E-E_0}{P_0c} & p_\sigma&=\frac{E-E_0}{\beta_0 P_0c} \end{aligned}$$

$$\begin{aligned} \delta&=\sqrt{p_t^2 + 2 p_t/\beta_0 +1} -1 & \frac{d \delta}{d p_t}= \frac{p_t+1/\beta_0}{1+\delta} = \frac{1}{\beta} \\ \delta&=\sqrt{\beta_0^2 p_\sigma^2 + 2 p_\sigma +1} -1 & \frac{d \delta}{d p_\sigma}= \frac{p_\sigma\beta_0^2+1}{1+\delta} = \frac{\beta_0}{\beta} \end{aligned}$$

$$\begin{aligned} p_z&=\sqrt{(1+\delta)^2 - p_x^2 - p_y^2} \\ \frac{d p_z}{d p_t}&= \frac{p_t+1/\beta_0}{p_z} = \frac{1}{\beta_z} \\ \frac{d p_z}{d p_\sigma}&= \frac{\beta_0^2 p_\sigma+1}{p_z} = \frac{\beta_0}{\beta_z} \end{aligned}$$

Simulation features

Lattice properties:

  • static lattice
  • dynamic lattice: properties of the elements of lattice can change predictably
  • collective effects (or feedbacks): properties of the elements of lattice depends on all particle trajectories

Data and IO:

  • observation points: output storage needs to be preallocated
  • scattering: particle loss and creation: simulation needs to be stopped and particles reshuffled from time to time.

Simulation parameters space:

  • one lattice, many turns few particles
  • one lattice, many particles few turns
  • slightly different lattices, few turns few particles
  • different bunches

Data layout:

  • sequence introspection

Data models:

  • deferred expressions, knobs, constraints, events
  • events: on change attribute (dep graphs), on change turn,

Computation flow:

  • case switch (dynamic structures, feedback, lambdas)
  • generated code (with constraints, dynamics)
  • small kernels (logic of dynamic structures, feedback, lambdas outside kernels)
  • big kernels (logic of dynamic structures, feedback, lambdas inside kernels)

Implementation

  • pure python (pytpsa, multiprecision, sympy, numba, numba+cuda, cupy)
  • c code (c+double, c+opencl, cuda, cffi, numba, pycuda, pyopencl, cupy)
  • c++ (c+double, c+cuda, c++ tpsa, pybind11, cppyy)
  • julias (native, cudanative, multiprecision)

Deployment:

  • in clusters
  • in boinc (c code, c+opencl, c+cuda)
  • locally (with gpu)

C API example

partid=add_particle(ctx, bunch, particle_specs)
elemid=add_element(ctx, namespace, name, element_specs)
seqid=add_sequence(ctx, namespace, name)
add_elem_to_sequence(ctx, seqid, elemid)
add_constraint(event, action)

Internal API

buff_new(buffer)->objid
buff_add_<type>(buffer,objid,value)
buff_add_<type>s(buffer,objid,length,&values)

buff_serialize(buffer)  ...
buff_deserialize(buffer) ...

buff_set_<type>(buffer,objid,offset,value)
buff_get_<type>(buffer,objid,offset) -> value
buff_get_<type>s(buffer,objid,offset) -> values[]

elem_set_<type>(&obj,offset,value)
elem_get_<type>(&obj,offset) -> value
elem_set_<type>s(&obj,offset,values,lengths)
elem_get_<type>s(&obj,offset) -> value

<elemname>_init(buffer,...values...) using
   buffer_new buffer_add... 
<elemname>_set_<name>(&obj,value)
<elemname>_get_<name>(&obj) -> &value
typeid
size
npointers
pointer offsets [npointers]
<data>
       switch (typeid) {
           case DriftID:
                Drift_track(particles, partid,
                            Drift_get_length(data,elemid)        );
           break;
           case MultipoleID:
                Multipole_track(p,
                               Multipole_get_order(data,elemid),
                               Multipole_get_l(data,elemid),
                               Multipole_get_hxl(data,elemid),
                               Multipole_get_hyl(data,elemid),
                               Multipole_get_bal(data,elemid)    );
           break;
           case CavityID:
                Cavity_track(p,
                               Cavity_get_volt(data,elemid),
                               Cavity_get_freq(data,elemid),
                               Cavity_get_lag(data,elemid)       );
           break;
           case AlignID:
                Align_track(p,
                               Align_get_cz(data,elemid),
                               Align_get_sz(data,elemid),
                               Align_get_dx(data,elemid),
                               Align_get_dy(data,elemid)    );
           break;