{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Longitudinal tracking simulations"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"S. Albright, H. Damerau, A. Lasheen, D. Quartullo, F. Tecker"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"## Links"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- Introductory CAS website: https://indico.cern.ch/event/1226773/\n",
"- Programme of the CAS: https://cas.web.cern.ch/sites/default/files/Timetable_Introductory2023_ver3.pdf\n",
"- Python software installation for transverse (and longitudinal) exercises: https://github.com/cerncas/hands-on-lattice-exercises/blob/master/Setup_Instructions.md\n",
"- Longitudinal hands-on, link to content and cheat sheets: https://indico.cern.ch/event/1226773/contributions/5161252/"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"## Introduction\n",
"\n",
"In this hands-on session we will experiment with particle tracking simulations.\n",
"\n",
"The goal of the session is to write a tracking code to observe the evolution of the particles in the longitudinal phase space ($\\phi$, $\\Delta E$), for each turn in the machine.\n",
"\n",
"The notebook is constructed with the following purpose in mind:\n",
"\n",
"1. Compute basic machine parameters (the example of the CERN scSPS is taken).\n",
"2. Writing the equations of motion in the form of a python function, to track a single particle.\n",
"3. Record and observe the trajectory of a particle in the longitudinal phase space.\n",
"4. Extend the tracking code to work with many particles, acceleration, below and above transition.\n",
"5. Analyze the particle motion and compare with analytical evaluations of the bucket area, height, synchrotron frequency.\n",
"6. Observe the evolution of a bunch of particles, and simulate the injection of a bunch in a synchrotron by adjusting the RF parameters to match the bunch to the RF bucket.\n",
"7. BONUS: include more complex features like multiple RF systems, synchrotron radiation, in the tracking loop.\n",
"\n",
"Along the exercises, you will be encouraged to use `support_functions`. These were designed to help you during the hands-on session by reducing the coding overhead. You can check the documentation of each function by calling `function?` in a new cell.\n",
"\n",
"The available support functions are\n",
"\n",
"| `support_functions.py` |\n",
"| ----------------------------- |\n",
"| plot_phase_space_trajectory |\n",
"| plot_phase_space_distribution |\n",
"| synchrotron_tune |\n",
"| separatrix |\n",
"| run_animation |\n",
"| oscillation_spectrum |\n",
"| synchrotron_tune |\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Importing modules"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# In this cell we import all modules that will be required for the computation\n",
"# You can add extra imports as you progress in the exercises\n",
"# Hint: use scipy.constants for elementary charge, speed of light, mass of a proton...\n",
"\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"from scipy.constants import e, c, m_p\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Basic accelerator and beam parameters"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Parameters of the Super Proton Synchrotron (SPS) at CERN\n",
"\n",
"| Parameter | |\n",
"| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |\n",
"| Energy range | $E_\\mathrm{kin} = 26\\,\\mathrm{GeV}...1300\\,\\mathrm{GeV}$ |\n",
"| Circumference | $2 \\pi R = 6911.5\\,\\mathrm{m}$ |\n",
"| Bending radius | $\\rho = 741.3\\,\\mathrm{m}$ |\n",
"| Transition gamma | $\\gamma_\\mathrm{tr} = 18.$ |\n",
"| Acceleration time | $4\\,\\mathrm{s}$ |\n",
"| Harmonic number | $4620$ |\n",
"| RF voltage at injection | $V_{\\mathrm{rf,inj}} = 4.5\\,\\mathrm{MV}$ |\n",
"| Maximum RF voltage | $V_{\\mathrm{rf,max}} = 15\\,\\mathrm{MV}$ |\n",
"| Longitudinal emittance per bunch | $\\varepsilon_\\mathrm{l} = 0.6\\,\\mathrm{eVs}$ |\n",
"| Maximum bucket filling factor | $\\varepsilon_\\mathrm{l}/A_\\mathrm{bucket} = 0.8$ |\n",
"| Total beam intensity | $N = 1.6 \\cdot 10^{14} \\,\\mathrm{protons}$ $(2 \\times 320\\mathrm{b} \\times 2.5 \\cdot 10^{11} \\mathrm{protons}/\\mathrm{bunch})$ |\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercise 1: Compute basic machine parameters\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"1. Compute the following parameters at the minimum/maximum energies\n",
" - $E$, $p$\n",
" - $\\beta$, $\\gamma$, $T_{\\mathrm{rev}}$, $f_{\\mathrm{rev}}$\n",
" - $f_{\\mathrm{rf}}$, $T_{\\mathrm{rf}}$\n",
" - $\\alpha_c$, $\\eta$\n",
"2. Some reflexion and crosscheck with respect to yesterday's hands-on exercises\n",
" - How large is the RF frequency sweep ?\n",
" - What is the bucket length ?\n",
" - Are we above/below transition ?"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Beta: 0.9993932358608412\n",
"Gamma: 28.710512044511262\n",
"Revolution period: 23.0682794443392 mus\n",
"RF frequency: 200.27501449110963 MHz\n",
"RF period: 4.993134078861298 ns\n",
"Momentum compaction factor: 0.0030864197530864196\n",
"Phase slippage factor: 0.0018732596374893458\n"
]
}
],
"source": [
"Ekin = 26e9 # 1.3e12\n",
"\n",
"charge = 1\n",
"E0 = m_p*c**2./e\n",
"circumference = 6911.5\n",
"energy = Ekin + E0\n",
"momentum = np.sqrt(energy**2. - E0**2.)\n",
"beta = momentum/energy\n",
"gamma = energy/E0\n",
"\n",
"t_rev = circumference/(beta*c)\n",
"f_rev = 1/t_rev\n",
"\n",
"harmonic = 4620\n",
"voltage = 4.5e6\n",
"f_rf = harmonic*f_rev\n",
"t_rf = 1/f_rf\n",
"\n",
"gamma_t = 18\n",
"alpha_c = 1/gamma_t**2.\n",
"eta = alpha_c - 1/gamma**2.\n",
"\n",
"print(\"Beta: \" +str(beta))\n",
"print(\"Gamma: \" +str(gamma))\n",
"print(\"Revolution period: \" +str(t_rev*1e6) + \" mus\")\n",
"print(\"RF frequency: \" +str(f_rf/1e6) + \" MHz\")\n",
"print(\"RF period: \" +str(t_rf*1e9) + \" ns\")\n",
"print(\"Momentum compaction factor: \" +str(alpha_c))\n",
"print(\"Phase slippage factor: \" +str(eta))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercise 2: Tracking with a single particle"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Write functions to track the particle coordinates following longitudinal equations of motion\n",
" $$\\phi_{n+1} = \\phi_n + 2 \\pi h \\eta \\frac{\\Delta E_n}{\\beta^2 E}$$\n",
" $$\\Delta E_{n+1} = \\Delta E_n + q V \\sin (\\phi_{n+1}) - U_0$$\n",
" - *Start with no acceleration or synchrotron radiation*\n",
"2. Define the initial coordinates of a particle in the $(\\phi, \\Delta E)$ phase space.\n",
"3. Simulate the evolution of the particle coordintates for few hundred turns and store the coordinates.\n",
" - *You can pre-allocate a numpy array with `np.zeros(n_turns)` and fill the particle coordinates each turn*\n",
" - *You can store the particle coordinates at each turn by appending the coordinates to a list*\n",
"4. Plot the evolution of the particle phase and energy vs. turn number, and the particle motion in longitudinal phase space\n",
" - *The support function `plot_phase_space_trajectory` can be used*"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercise 3: Track with a few particles at different amplitudes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Repeat the same operations as in Exercise 2, starting with several particles\n",
" - *You can simply add more particles with different variable names*\n",
" - *You can generate numpy arrays representing several particles as `np.array([phase_1, phase_2, phase_3])`*\n",
" - *You can store the trajectories of the particles in a pre-allocated array of size `np.zeros((n_turns, n_particles))`*\n",
"2. Track the evolution of particles including with large offsets in $\\phi$ and $\\Delta E$\n",
" - *What happens when particles are too far from the synchronous particle?*\n",
"3. Generate about 10 particles at $\\Delta E=0$ with different phases, and simulate for a few turns\n",
" - *You can use `np.linspace(phase_start, phase_end, n_particles)` to linearly space particles in phase*\n",
" - *What can you observe regarding the velocity of the particles in phase space, vs. the maximum amplitude in phase?*\n",
"4. Plot the separatrix on top of your plot\n",
" - *Use the `separatrix` support_function to generate the separatrix.*\n",
" - *You can pass the separatrix to the `plot_phase_space_trajectory` to combine plots*"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercise 4: Acceleration"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Track the particles by adding the acceleration term, which can be evaluated from the parameter table above\n",
" - *For simplicity we will neglect here the variations in $\\beta$, $\\gamma$, $T$, $\\omega$...*\n",
"2. What is the influence on the particle trajectories ?\n",
" - *You can repeat the same tests as in the previous exercises.*\n",
"3. What happens if the ramp rate is twice as fast? Or the voltage is halved?\n",
"4. What happens if the beam is decelerated instead?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercise 5: On the other side of transition energy"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. What if the injection kinetic energy was 14 GeV instead of 26 GeV?\n",
"2. What does that change for the bucket and why?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercise 6: Comparison with analytical evaluations"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Calculate the height and area of the stationary bucket analytically for lower/higher beam energies.\n",
"2. Determine analytically the synchrotron frequency at the centre of the stationary bucket.\n",
"3. Compare qualitatively the results you obtained with the tracking\n",
" - *These analytical calculations serve to benchmark the tracking simulations.*\n",
" - *You can also compare with the accelerating cases.*"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercise 7: Mismatched distribution, bunch rotation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Generate a bunch distribution using the `generate_bunch` function.\n",
" - *Use the `plot_phase_space_distribution` to plot the distribution in phase space*\n",
" - *Use your tracking routine to see the bunch distribution before/after tracking*\n",
" - *Use the `run_animation` function to monitor the evolution of the distribution while tracking*\n",
" - *For the `run_animation` please call if you have trouble with the function syntax*\n",
"2. Try to match the bunch to the bucket. Track it for many synchrotron periods.\n",
"3. Introduce a phase or energy error between bunch and bucket.\n",
"4. Introduce a voltage mismatch. What do you observe?\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercise 8: Non-linear synchrotron frequency distribution, comparison with analytical formula"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Track a few tens of particles for a few synchrotron periods to analyze the frequency of synchrotron oscillation.\n",
" - *You can start with the same script as in Exercise 3 to start with few particles.*\n",
" - *The function `oscillation_spectrum` returns the spectrum of phase or energy oscillations for a given particle.*\n",
" - *The function `synchrotron_tune` returns the tune of a given particle, based on the maximum of the oscillation spectrum obtained with FFT.*\n",
"2. Plot the synchrotron frequency versus phase or energy offset. This illustrates the synchrotron frequency distribution.\n",
" - *Beware of particles extremely close to the center of the bucket or exactly on the separatrix*\n",
"3. Compare with the expected depedence of the non-linear synchrotron tune from the cheat sheet.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercises, to infinity and beyond..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- Include synchrotron radiation at 1.3 TeV\n",
"- Add second harmonic RF system in the tracking\n",
"- What happens when operating both RF systems in phase (bunch-shortening) or in counterphase (bunch-lengthening)?\n",
"- Check the effect on the synchrotron frequency.\n",
"- Animate the evolution of the bunch distribution for the test cases of exercise 9.\n"
]
}
],
"metadata": {
"@webio": {
"lastCommId": null,
"lastKernelId": null
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.12"
},
"vscode": {
"interpreter": {
"hash": "5799a97a65865a25ecdf3ee666151758480b049426fd4243ca03514702a0ab79"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}