Skip to content

Commit 30f86a7

Browse files
authored
tbt optics correction
To do: -apply_correction function to be replace by SC.set_magnet_setpoints -Coupling RDTs correction to be added
1 parent 425c73e commit 30f86a7

File tree

1 file changed

+79
-0
lines changed
  • pySC/correction

1 file changed

+79
-0
lines changed

pySC/correction/tbt

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import numpy as np
2+
import at
3+
4+
def phase_advance_correction(ring, bpm_indices, elements_indices, dkick, cut, Px=None, Py=None, Etax=None):
5+
"""
6+
Perform phase advance and horizontal dispersion correction on the given ring.
7+
8+
Parameters:
9+
dkick: Change in quadrupole strength for response matrix calculation.
10+
cut: number of kept singular values
11+
Px, Py, Etax: response matrices for horizontal and vertical phase advances and dispersion.
12+
If not provided, they will be calculated.
13+
14+
Returns:
15+
corrected ring
16+
"""
17+
# Initial Twiss parameters
18+
_, _, twiss_err0 = at.get_optics(ring, bpm_indices)
19+
elemdata0, beamdata, elemdata = at.get_optics(ring, bpm_indices)
20+
mux0 = elemdata.mu[:, 0] / (2 * np.pi)
21+
muy0 = elemdata.mu[:, 1] / (2 * np.pi)
22+
Eta_x0 = elemdata.dispersion[:, 0]
23+
24+
# Calculate Response Matrix if not provided
25+
if Px is None or Py is None or Etax is None:
26+
Px, Py, Etax = calculate_rm(dkick, ring, elements_indices, bpm_indices, mux0, muy0, Eta_x0)
27+
28+
response_matrix = np.hstack((Px, Py, Etax))
29+
30+
elemdata0, beamdata, elemdata = at.get_optics(ring, bpm_indices)
31+
mux = elemdata.mu[:, 0] / (2 * np.pi)
32+
muy = elemdata.mu[:, 1] / (2 * np.pi)
33+
Eta_xx = elemdata.dispersion[:, 0]
34+
35+
measurement = np.concatenate((mux - mux0, muy - muy0, Eta_xx - Eta_x0), axis=0)
36+
37+
s = np.linalg.svd(response_matrix.T, compute_uv=False)
38+
system_solution = np.linalg.pinv(response_matrix.T, rcond=s[cut - 1] / s[0]) @ -measurement
39+
ring = apply_correction(ring, system_solution, elements_indices)
40+
41+
return ring
42+
43+
44+
def calculate_rm(dkick, ring, elements_indices, bpm_indices, mux0, muy0, Eta_x0):
45+
"""
46+
Returns:
47+
Px, Py, Etax: Response matrices for horizontal and vertical phase advances and dispersion.
48+
"""
49+
px =[]
50+
py =[]
51+
etax = []
52+
53+
for index in elements_indices:
54+
original_setting = ring[index].PolynomB[1]
55+
56+
ring[index].PolynomB[1] += dkick
57+
_, _, elemdata = at.get_optics(ring, bpm_indices)
58+
59+
mux = elemdata.mu[:, 0] / (2 * np.pi)
60+
muy = elemdata.mu[:, 1] / (2 * np.pi)
61+
Eta_x = elemdata.dispersion[:, 0]
62+
63+
px.append((mux - mux0) / dkick)
64+
py.append((muy - muy0) / dkick)
65+
etax.append((Eta_x - Eta_x0) / dkick)
66+
67+
ring[index].PolynomB[1] = original_setting
68+
69+
Px = np.squeeze(np.array(px))
70+
Py = np.squeeze(np.array(py))
71+
Etax = np.squeeze(np.array(etax))
72+
73+
return Px, Py, Etax
74+
75+
76+
def apply_correction(ring, corrections, elements_indices):
77+
for i, index in enumerate(elements_indices):
78+
ring[index].PolynomB[1] += corrections[i]
79+
return ring

0 commit comments

Comments
 (0)