|
| 1 | +# copyright ################################# # |
| 2 | +# This file is part of the Xfields Package. # |
| 3 | +# Copyright (c) CERN, 2021. # |
| 4 | +# ########################################### # |
| 5 | +import matplotlib.pyplot as plt |
| 6 | +import xtrack as xt |
| 7 | +from scipy.constants import e |
| 8 | + |
| 9 | +########################## |
| 10 | +# Load xt.Line from file # |
| 11 | +########################## |
| 12 | + |
| 13 | +fname_line_particles = "../../../xtrack/test_data/bessy3/bessy3.json" |
| 14 | +line = xt.Line.from_json(fname_line_particles) # has particle_ref |
| 15 | +line.build_tracker() |
| 16 | + |
| 17 | +######################## |
| 18 | +# Twiss with Radiation # |
| 19 | +######################## |
| 20 | + |
| 21 | +# We need to Twiss with Synchrotron Radiation enabled to obtain |
| 22 | +# the SR equilibrium emittances and damping constants |
| 23 | + |
| 24 | +line.matrix_stability_tol = 1e-2 |
| 25 | +line.configure_radiation(model="mean") |
| 26 | +line.compensate_radiation_energy_loss() |
| 27 | +tw = line.twiss(eneloss_and_damping=True) |
| 28 | + |
| 29 | +###################################### |
| 30 | +# Steady-State Emittance Calculation # |
| 31 | +###################################### |
| 32 | + |
| 33 | +bunch_intensity = 1e-9 / e # 1C bunch charge |
| 34 | +emittance_coupling_factor = 1 # round beam |
| 35 | + |
| 36 | +# If not providing starting emittances, the function will |
| 37 | +# default to the SR equilibrium emittances from the TwissTable |
| 38 | + |
| 39 | +result = tw.get_ibs_and_synrad_emittance_evolution( |
| 40 | + formalism="nagaitsev", # can also be "bjorken-mtingwa" |
| 41 | + total_beam_intensity=bunch_intensity, |
| 42 | + # gemitt_x=..., # defaults to tw.eq_gemitt_x |
| 43 | + # gemitt_y=..., # defaults to tw.eq_gemitt_x |
| 44 | + # gemitt_zeta=..., # defaults to tw.eq_gemitt_zeta |
| 45 | + emittance_coupling_factor=emittance_coupling_factor, |
| 46 | + emittance_constraint="coupling", |
| 47 | +) |
| 48 | + |
| 49 | +# The returned object is an xtrack Table |
| 50 | +print(result) |
| 51 | + |
| 52 | +# Table: 1089 rows, 9 cols |
| 53 | +# time gemitt_x nemitt_x gemitt_y nemitt_y gemitt_zeta nemitt_zeta sigma_zeta sigma_delta Kx Ky Kz |
| 54 | +# 1.2104374139405318e-06 6.8355e-11 3.34418e-07 6.8355e-11 3.34418e-07 3.38167e-06 0.0581296 0.00344698 0.000981052 58.4838 -0.0165806 17.0318 |
| 55 | +# 9.306647341196751e-05 6.87219e-11 3.36214e-07 6.87219e-11 3.36214e-07 3.39225e-06 0.0583114 0.00345237 0.000982586 58.4736 -0.0165775 17.0292 |
| 56 | +# 0.0001849225094099945 6.90808e-11 3.37969e-07 6.90808e-11 3.37969e-07 3.40267e-06 0.0584907 0.00345767 0.000984095 57.7058 -0.0163509 16.8361 |
| 57 | +# ... |
| 58 | +# 0.0997568655312697 8.4492e-11 4.13367e-07 8.4492e-11 4.13367e-07 4.51774e-06 0.0776582 0.00398413 0.00113393 29.799 -0.00861232 8.14787 |
| 59 | +# 0.09984872156726772 8.4492e-11 4.13367e-07 8.4492e-11 4.13367e-07 4.51774e-06 0.0776583 0.00398413 0.00113393 29.799 -0.00861232 8.14786 |
| 60 | +# 0.09994057760326575 8.44919e-11 4.13367e-07 8.44919e-11 4.13367e-07 4.51775e-06 0.0776584 0.00398414 0.00113393 29.799 -0.00861232 8.14784 |
| 61 | + |
| 62 | +###################################### |
| 63 | +# Comparison with analytical results # |
| 64 | +###################################### |
| 65 | + |
| 66 | +# These are analytical estimate (from the last step's IBS growth rates) |
| 67 | +# The factor below is to be respected with the coupling constraint |
| 68 | +factor = 1 + emittance_coupling_factor * (tw.partition_numbers[1] / tw.partition_numbers[0]) |
| 69 | +analytical_x = result.gemitt_x[0] / (1 - result.Kx[-1] / (tw.damping_constants_s[0] * factor)) |
| 70 | +analytical_y = result.gemitt_y[0] / (1 - result.Kx[-1] / (tw.damping_constants_s[0] * factor)) |
| 71 | +analytical_z = result.gemitt_zeta[0] / (1 - result.Kz[-1] / (tw.damping_constants_s[2])) |
| 72 | + |
| 73 | +print() |
| 74 | +print("Emittance Constraint: Coupling") |
| 75 | +print("Horizontal steady-state emittance:") |
| 76 | +print("---------------------------------") |
| 77 | +print(f"Analytical: {analytical_x}") |
| 78 | +print(f"ODE: {result.eq_sr_ibs_gemitt_x}") |
| 79 | +print("Vertical steady-state emittance:") |
| 80 | +print("-------------------------------") |
| 81 | +print(f"Analytical: {analytical_y}") |
| 82 | +print(f"ODE: {result.eq_sr_ibs_gemitt_y}") |
| 83 | +print("Longitudinal steady-state emittance:") |
| 84 | +print("-----------------------------------") |
| 85 | +print(f"Analytical: {analytical_z}") |
| 86 | +print(f"ODE: {result.eq_sr_ibs_gemitt_zeta}") |
| 87 | + |
| 88 | +# Emittance Constraint: Coupling |
| 89 | +# Horizontal steady-state emittance: |
| 90 | +# --------------------------------- |
| 91 | +# Analytical: 8.450195693021898e-11 |
| 92 | +# ODE: 8.449194372183254e-11 |
| 93 | +# Vertical steady-state emittance: |
| 94 | +# ------------------------------- |
| 95 | +# Analytical: 8.450195693021898e-11 |
| 96 | +# ODE: 8.449194372183254e-11 |
| 97 | +# Longitudinal steady-state emittance: |
| 98 | +# ----------------------------------- |
| 99 | +# Analytical: 4.518939710729963e-06 |
| 100 | +# ODE: 4.5177482475985255e-06 |
| 101 | + |
| 102 | +# The results from the table can easily be plotted to view |
| 103 | +# at the evolution of various parameters across time steps |
| 104 | + |
| 105 | +#!end-doc-part |
| 106 | +# fmt: off |
| 107 | + |
| 108 | +fig, (ax0, ax1) = plt.subplots(2, 1, sharex=True, layout="constrained") |
| 109 | + |
| 110 | +(l1,) = ax0.plot(result.time * 1e3, result.gemitt_x * 1e12, ls="-", label=r"$\tilde{\varepsilon}_x$") |
| 111 | +(l2,) = ax0.plot(result.time * 1e3, result.gemitt_y * 1e12, ls="--", label=r"$\tilde{\varepsilon}_y$") |
| 112 | +l4 = ax0.axhline(analytical_x * 1e12, color="C0", ls="-.", label=r"Analytical $\varepsilon_{x}^{eq}$") |
| 113 | +l5 = ax0.axhline(analytical_y * 1e12, color="C1", ls="-.", label=r"Analytical $\varepsilon_{y}^{eq}$") |
| 114 | +ax0b = ax0.twinx() |
| 115 | +(l3,) = ax0b.plot(result.time * 1e3, result.gemitt_zeta * 1e6, color="C2", label=r"$\varepsilon_z$") |
| 116 | +l6 = ax0b.axhline(analytical_z * 1e6, color="C2", ls="-.", label=r"Analytical $\varepsilon_{\zeta}^{eq}$") |
| 117 | +ax0.legend(handles=[l1, l2, l3, l4, l5], ncols=2) |
| 118 | + |
| 119 | +ax1.plot(result.time * 1e3, result.Kx, label=r"$K_{x}^{IBS}$") |
| 120 | +ax1.plot(result.time * 1e3, result.Ky, label=r"$K_{y}^{IBS}$") |
| 121 | +ax1.plot(result.time * 1e3, result.Kz, label=r"$K_{z}^{IBS}$") |
| 122 | +ax1.legend() |
| 123 | + |
| 124 | +ax1.set_xlabel("Time [ms]") |
| 125 | +ax0.set_ylabel(r"$\tilde{\varepsilon}_{x,y}$ [pm.rad]") |
| 126 | +ax0b.set_ylabel(r"$\varepsilon_{\zeta}$ [m]") |
| 127 | +ax1.set_ylabel(r"$K_{x,y,z}^{IBS}$ [$s^{-1}$]") |
| 128 | +fig.align_ylabels((ax0, ax1)) |
| 129 | +plt.tight_layout() |
| 130 | +plt.show() |
0 commit comments