Skip to content

Commit 4e8a446

Browse files
committed
First Ne tests and runs
1 parent 0425159 commit 4e8a446

File tree

7 files changed

+178
-6
lines changed

7 files changed

+178
-6
lines changed

data/acc-models-sps

Submodule acc-models-sps updated from 83418f1 to beb2353
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from .sps_beam_parameters import BeamParameters_SPS, BeamParameters_SPS_2024_2b, BeamParameters_SPS_Binomial_2016, BeamParameters_SPS_Binomial_2016_before_RF_capture, BeamParameters_SPS_Oxygen, BeamParameters_SPS_Proton
1+
from .sps_beam_parameters import BeamParameters_SPS, BeamParameters_SPS_2024_2b, BeamParameters_SPS_Binomial_2016, BeamParameters_SPS_Binomial_2016_before_RF_capture, BeamParameters_SPS_Oxygen, BeamParameters_SPS_Proton, BeamParameters_SPS_Neon

fma_ions/beam_parameters/sps_beam_parameters.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,16 @@ class BeamParameters_SPS_Oxygen:
7474
eyn: float = 0.9e-6
7575
m : float = 9 # dummy value, not needed if q-Gaussian is used
7676

77+
@dataclass
78+
class BeamParameters_SPS_Neon:
79+
"""Data Container for SPS Neon beam parameters"""
80+
Nb: float = 2.37e9 # measured on 2025-07-07
81+
sigma_z: float = 0.26 # use 2025-07-03 WCM measurement with q-Gaussian fit, assume same as oxygen
82+
q : float = 0.37 # q-Gaussian parameter after RF spill --> use 2025-07-03 WCM measurement
83+
exn: float = 1.03e-6 # measured on 2025-07-07 evening
84+
eyn: float = 1.2e-6 # measured on 2025-07-07 evening
85+
m : float = 9 # dummy value, not needed if q-Gaussian is used
86+
7787
@dataclass
7888
class BeamParameters_SPS_Proton:
7989
"""

fma_ions/sequences/sequence_classes_sps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class SPS_sequence_maker:
4646
optics: str
4747
absolute path to optics repository -> cloned from https://gitlab.cern.ch/acc-models
4848
"""
49-
ion_type: str = 'Pb' # Define beam type - default is Pb
49+
ion_type: str = 'Pb' # Define beam type - default is Pb, also O, Ne are possible
5050
qx0: float = 26.30
5151
qy0: float = 26.19
5252
dq1: float = -0.367 if ion_type == 'Pb' else 0.174 # ion values measured 2024-11-19, proton vals: knobs + Ingrid

fma_ions/sps_flat_bottom_tracking.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import xfields as xf
1212
import xobjects as xo
1313

14-
from .beam_parameters import BeamParameters_SPS, BeamParameters_SPS_Binomial_2016, BeamParameters_SPS_Binomial_2016_before_RF_capture, BeamParameters_SPS_Oxygen, BeamParameters_SPS_Proton
14+
from .beam_parameters import BeamParameters_SPS, BeamParameters_SPS_Binomial_2016, BeamParameters_SPS_Binomial_2016_before_RF_capture, BeamParameters_SPS_Oxygen, BeamParameters_SPS_Proton, BeamParameters_SPS_Neon
1515

1616
from .sequences import SPS_sequence_maker
1717
from .tune_ripple import Tune_Ripple_SPS
@@ -141,7 +141,7 @@ def track_SPS(self,
141141
Parameters:
142142
----------
143143
ion_type : str
144-
which ion to use: currently available are 'Pb' and 'O'
144+
which ion to use: currently available are 'Pb' and 'O' and 'Ne'
145145
which_context : str
146146
'gpu' or 'cpu'
147147
add_non_linear_magnet_errors : bool
@@ -242,6 +242,8 @@ def track_SPS(self,
242242
beamParams = BeamParameters_SPS()
243243
if ion_type=='O':
244244
beamParams = BeamParameters_SPS_Oxygen()
245+
if ion_type=='Ne':
246+
beamParams = BeamParameters_SPS_Neon()
245247
if ion_type=='proton':
246248
beamParams = BeamParameters_SPS_Proton()
247249
harmonic_nb = 4620 # update harmonic number
@@ -266,7 +268,9 @@ def track_SPS(self,
266268
if ion_type=='Pb' or ion_type=='proton':
267269
sps = SPS_sequence_maker(ion_type=ion_type, proton_optics=self.proton_optics, qx0=self.qx0, qy0=self.qy0)
268270
elif ion_type=='O':
269-
sps = SPS_sequence_maker(ion_type='O', Q_PS=4., Q_SPS=8., m_ion=15.9949, proton_optics=self.proton_optics, qx0=self.qx0, qy0=self.qy0)
271+
sps = SPS_sequence_maker(ion_type='O', Q_PS=4., Q_SPS=8., m_ion=15.9949, proton_optics=self.proton_optics, qx0=self.qx0, qy0=self.qy0)
272+
elif ion_type=='Ne':
273+
sps = SPS_sequence_maker(ion_type='Ne', Q_PS=5., Q_SPS=10., m_ion=20.1797, proton_optics=self.proton_optics, qx0=self.qx0, qy0=self.qy0)
270274
else:
271275
raise ValueError('Only Pb and O ions implemented so far!')
272276

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"""
2+
Launcher script to HTCondor for GPU - generate python scripts for tune scan
3+
"""
4+
import fma_ions
5+
import os
6+
import pathlib
7+
import numpy as np
8+
import datetime
9+
10+
# Find path of script being run
11+
dir_path = pathlib.Path(__file__).parent.absolute()
12+
13+
# Define run files and which parameters to change
14+
master_name = 'SPS_Ne_ions_sc_ibs_with_comp_50_150_300_600_Hz_ripple_130k_and_476k_turns_2025_07_07'
15+
num_turns = [130_000, 476_000]
16+
Qx = 26.31
17+
Qy = 26.25
18+
19+
# Use measured 2025-06-17 O8+ SPS values
20+
run_files = ['sps_Ne_scan_run_{}.py'.format(i+1) for i in range(len(num_turns))]
21+
22+
# Define script and folder names
23+
script_names = run_files.copy()
24+
folder_names = ['sps_Ne_Nb_scan_{}'.format(i) for i in range(len(num_turns))]
25+
string_array = ['SPS N case = {}'.format(i) for i in range(len(num_turns))]
26+
27+
# Generate the scripts to be submitted
28+
for i, run_file in enumerate(run_files):
29+
30+
# Write run file for given tune
31+
print('Generating launch script {}\n'.format(run_file))
32+
run_file = open(run_file, 'w')
33+
run_file.truncate(0) # remove existing content, if any
34+
run_file.write(
35+
'''import fma_ions
36+
import numpy as np
37+
output_dir = './'
38+
39+
n_turns = {}
40+
num_part = 20_000
41+
42+
# Transfer function factors
43+
a_50 = 1.0 #1.7170
44+
a_150 = 0.5098
45+
a_300 = 0.2360
46+
a_600 = 0.1095
47+
48+
# Desired ripple frequencies and amplitudes - from DCCT measurements 2024-10-30
49+
ripple_freqs = np.array([50.0, 150.0, 300.0, 600.0])
50+
kqf_amplitudes = np.array([1.79381965522221e-07*a_50, 1.7917856960711038e-07*a_150, 1.717715125357188e-07*a_300, 1.0613897587376263e-07*a_600])
51+
kqd_amplitudes = np.array([3.1433458408493135e-07*a_50, 4.125645646596158e-07*a_150, 2.6325770762187453e-07*a_300, 8.302889259074001e-08*a_600])
52+
kqf_phases = np.array([2.5699456856082965, -1.2707524434033985, 1.1509405507521766, -2.3897351868985552])
53+
kqd_phases = np.array([-1.6168418898711074, -1.5349070763197448, -2.145386063404577, 0.7431459693919794])
54+
55+
# Tracking on GPU context
56+
sps = fma_ions.SPS_Flat_Bottom_Tracker(qx0={:.3f}, qy0={:.3f}, num_turns=n_turns, num_part=num_part)
57+
tbt = sps.track_SPS(ion_type='Ne', which_context='gpu', distribution_type='qgaussian', install_SC_on_line=True, add_beta_beat=True,
58+
add_non_linear_magnet_errors=True, apply_kinetic_IBS_kicks=True, ibs_step = 2000, add_tune_ripple=True, ripple_freqs = ripple_freqs,
59+
kqf_amplitudes = kqf_amplitudes, kqd_amplitudes = kqd_amplitudes, kqf_phases=kqf_phases, kqd_phases=kqd_phases,
60+
SC_adaptive_interval_during_tracking=100)
61+
tbt.to_json(output_dir)
62+
'''.format(num_turns[i], Qx, Qy)
63+
)
64+
run_file.close()
65+
66+
67+
# Instantiate the submitter class and launch the jobs
68+
sub = fma_ions.Submitter()
69+
master_job_name = '{:%Y_%m_%d__%H_%M_%S}_{}'.format(datetime.datetime.now(), master_name)
70+
71+
# Launch the Python scripts in this folder
72+
for i, script in enumerate(script_names):
73+
file_name = os.path.join(dir_path, script)
74+
print(f"Submitting {file_name}")
75+
sub.submit_GPU(file_name, master_job_name=master_job_name, job_name=folder_names[i])
76+
sub.copy_master_plot_script(folder_names, string_array)
77+
sub.copy_plot_script_emittances_for_scan(master_name, folder_names, scan_array_for_x_axis=Nb_array,
78+
label_for_x_axis='Injected Pb ions per bunch',
79+
extra_text_string='$Q_{x, y}$ = 26.31, 26.25 - q-Gaussian beam\\nAdaptive SC, ~10% $\\beta$-beat + non-linear magnet errors')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"""
2+
Launcher script to HTCondor for GPU - generate python scripts for tune scan
3+
"""
4+
import fma_ions
5+
import os
6+
import pathlib
7+
import numpy as np
8+
import datetime
9+
10+
# Find path of script being run
11+
dir_path = pathlib.Path(__file__).parent.absolute()
12+
13+
# Define run files and which parameters to change
14+
master_name = 'SPS_Ne_ions_sc_ibs_with_no_comp_50_150_300_600_Hz_ripple_130k_and_476k_turns_2025_07_07'
15+
num_turns = [130_000, 476_000]
16+
Qx = 26.31
17+
Qy = 26.25
18+
19+
# Use measured 2025-06-17 O8+ SPS values
20+
run_files = ['sps_Ne_scan_run_{}.py'.format(i+1) for i in range(len(num_turns))]
21+
22+
# Define script and folder names
23+
script_names = run_files.copy()
24+
folder_names = ['sps_Ne_Nb_scan_{}'.format(i) for i in range(len(num_turns))]
25+
string_array = ['SPS N case = {}'.format(i) for i in range(len(num_turns))]
26+
27+
# Generate the scripts to be submitted
28+
for i, run_file in enumerate(run_files):
29+
30+
# Write run file for given tune
31+
print('Generating launch script {}\n'.format(run_file))
32+
run_file = open(run_file, 'w')
33+
run_file.truncate(0) # remove existing content, if any
34+
run_file.write(
35+
'''import fma_ions
36+
import numpy as np
37+
output_dir = './'
38+
39+
n_turns = {}
40+
num_part = 20_000
41+
42+
# Transfer function factors
43+
a_50 = 1.0 #1.7170
44+
a_150 = 0.5098
45+
a_300 = 0.2360
46+
a_600 = 0.1095
47+
48+
# Desired ripple frequencies and amplitudes - from DCCT measurements 2024-10-30
49+
ripple_freqs = np.array([50.0, 150.0, 300.0, 600.0])
50+
kqf_amplitudes = np.array([1.0141062492337905e-06*a_50, 1.9665396648867768e-07*a_150, 3.1027971430227987e-07*a_300, 4.5102937494506313e-07*a_600])
51+
kqd_amplitudes = np.array([1.0344583265981035e-06*a_50, 4.5225494700433166e-07*a_150, 5.492718035100028e-07*a_300, 4.243698659233664e-07*a_600])
52+
kqf_phases = np.array([0.7646995873548973, 2.3435670020522825, -1.1888958255027886, 2.849205512655574])
53+
kqd_phases = np.array([0.6225130389353318, -1.044380492147742, -1.125401419249802, -0.30971750008702853])
54+
55+
# Tracking on GPU context
56+
sps = fma_ions.SPS_Flat_Bottom_Tracker(qx0={:.3f}, qy0={:.3f}, num_turns=n_turns, num_part=num_part)
57+
tbt = sps.track_SPS(ion_type='Ne', which_context='gpu', distribution_type='qgaussian', install_SC_on_line=True, add_beta_beat=True,
58+
add_non_linear_magnet_errors=True, apply_kinetic_IBS_kicks=True, ibs_step = 2000, add_tune_ripple=True, ripple_freqs = ripple_freqs,
59+
kqf_amplitudes = kqf_amplitudes, kqd_amplitudes = kqd_amplitudes, kqf_phases=kqf_phases, kqd_phases=kqd_phases,
60+
SC_adaptive_interval_during_tracking=100)
61+
tbt.to_json(output_dir)
62+
'''.format(num_turns[i], Qx, Qy)
63+
)
64+
run_file.close()
65+
66+
67+
# Instantiate the submitter class and launch the jobs
68+
sub = fma_ions.Submitter()
69+
master_job_name = '{:%Y_%m_%d__%H_%M_%S}_{}'.format(datetime.datetime.now(), master_name)
70+
71+
# Launch the Python scripts in this folder
72+
for i, script in enumerate(script_names):
73+
file_name = os.path.join(dir_path, script)
74+
print(f"Submitting {file_name}")
75+
sub.submit_GPU(file_name, master_job_name=master_job_name, job_name=folder_names[i])
76+
sub.copy_master_plot_script(folder_names, string_array)
77+
sub.copy_plot_script_emittances_for_scan(master_name, folder_names, scan_array_for_x_axis=Nb_array,
78+
label_for_x_axis='Injected Pb ions per bunch',
79+
extra_text_string='$Q_{x, y}$ = 26.31, 26.25 - q-Gaussian beam\\nAdaptive SC, ~10% $\\beta$-beat + non-linear magnet errors')

0 commit comments

Comments
 (0)