Freeze longitudinal coordinates

In certain studies, it is convenient to track particles updating only the transverse coordinates, while keeping the longitudinal coordinates fixed (frozen). Xsuite offers the possibility to freeze the longitudinal coordinates within a single method or changing the state of the Line, as illustrated in the following sections.

Freezing longitudinal when calling methods

The Line.twiss and Line.track can work with frozen longitudinal coordinates. This is done by setting the freeze_longitudinal argument to True, as shown in the following example:

import json

import xtrack as xt
import xpart as xp

fname_line = '../../test_data/lhc_no_bb/line_and_particle.json'

# import a line and add reference particle
with open(fname_line) as fid:
    line_dict = json.load(fid)
line = xt.Line.from_dict(line_dict['line'])
line.particle_ref = xp.Particles.from_dict(line_dict['particle'])

# Build the tracker
line.build_tracker()

# Track some particles with frozen longitudinal coordinates
particles = line.build_particles(delta=1e-3, x=[-1e-3, 0, 1e-3])
line.track(particles, num_turns=10, freeze_longitudinal=True)
print(particles.delta) # gives [0.001 0.001 0.001], same as initial value

# Twiss with frozen longitudinal coordinates (needs to be 4d)
twiss = line.twiss(method='4d', freeze_longitudinal=True)
print(twiss.slip_factor) # gives 0 (no longitudinal motion)

# Track some particles with unfrozen longitudinal coordinates
particles = line.build_particles(delta=1e-3, x=[-1e-3, 0, 1e-3])
line.track(particles, num_turns=10)
print(particles.delta) # gives [0.00099218, ...], different from initial value

# Twiss with unfrozen longitudinal coordinates (can be 6d)
twiss = line.twiss(method='6d')
print(twiss.slip_factor) # gives 0.00032151, from longitudinal motion

Freezing longitudinal coordinates a with block

A context manager is also available to freeze the longitudinal coordinates within a with block. The normal tracking mode, updating the longitudinal coordinates, is automatically restored when exiting the with block, as it is illustrated in the following example:

import json

import xtrack as xt
import xpart as xp

fname_line = '../../test_data/lhc_no_bb/line_and_particle.json'

# import a line and add reference particle
with open(fname_line) as fid:
    line_dict = json.load(fid)
line = xt.Line.from_dict(line_dict['line'])
line.particle_ref = xp.Particles.from_dict(line_dict['particle'])

# Build the tracker
line.build_tracker()

# Perform a set of operations with frozen longitudinal coordinates
with xt.freeze_longitudinal(line):
    # Track some particles with frozen longitudinal coordinates
    particles = line.build_particles(delta=1e-3, x=[-1e-3, 0, 1e-3])
    line.track(particles, num_turns=10)
    print(particles.delta) # gives [0.001 0.001 0.001], same as initial value

    # Twiss with frozen longitudinal coordinates (needs to be 4d)
    twiss = line.twiss(method='4d')
    print(twiss.slip_factor) # gives 0 (no longitudinal motion)

# 6d tracking is automatically restored when the with block is exited

# Track some particles with unfrozen longitudinal coordinates
particles = line.build_particles(delta=1e-3, x=[-1e-3, 0, 1e-3])
line.track(particles, num_turns=10)
print(particles.delta) # gives [0.00099218, ...], different from initial value

# Twiss with unfrozen longitudinal coordinates (can be 6d)
twiss = line.twiss(method='6d')
print(twiss.slip_factor) # gives 0.00032151, from longitudinal motion

Freezing longitudinal coordinates with Line method

The xtrack.Line class provides a method called freeze_longitudinal() to explicitly freeze the longitudinal coordinates. The normal tracking mode, updating the longitudinal coordinates, can be restored by calling freeze_longitudinal(False). This is illustrated in the following example:

import json

import xtrack as xt
import xpart as xp

fname_line = '../../test_data/lhc_no_bb/line_and_particle.json'

# import a line and add reference particle
with open(fname_line) as fid:
    line_dict = json.load(fid)
line = xt.Line.from_dict(line_dict['line'])
line.particle_ref = xp.Particles.from_dict(line_dict['particle'])

# Build the tracker
line.build_tracker()

# Freeze longitudinal coordinates
line.freeze_longitudinal()

# Track some particles with frozen longitudinal coordinates
particles = line.build_particles(delta=1e-3, x=[-1e-3, 0, 1e-3])
line.track(particles, num_turns=10)
print(particles.delta) # gives [0.001 0.001 0.001], same as initial value

# Twiss with frozen longitudinal coordinates (needs to be 4d)
twiss = line.twiss(method='4d')
print(twiss.slip_factor) # gives 0 (no longitudinal motion)

# Unfreeze longitudinal coordinates
line.freeze_longitudinal(False)

# Track some particles with unfrozen longitudinal coordinates
particles = line.build_particles(delta=1e-3, x=[-1e-3, 0, 1e-3])
line.track(particles, num_turns=10)
print(particles.delta) # gives [0.00099218, ...], different from initial value

# Twiss with unfrozen longitudinal coordinates (can be 6d)
twiss = line.twiss(method='6d')
print(twiss.slip_factor) # gives 0.00032151, from longitudinal motion