Match twiss parameters

The Xtrack Line class provides a match method that allows to match the twiss parameters of a to adjust knobs attached to the line in order to obtain desired values in the twiss results. This feature is illustrated in the following examples.

Match tunes and chromaticities

See also xtrack.Line.match()

import json
import time
import xtrack as xt
import xpart as xp

###################################
# Load a line and build a tracker #
####################################

with open('../../test_data/hllhc15_noerrors_nobb/line_w_knobs_and_particle.json') as f:
    dct = json.load(f)

line = xt.Line.from_dict(dct['line'])
line.particle_ref = xp.Particles.from_dict(dct['particle'])
line.build_tracker()

#########
# Twiss #
#########

tw_before = line.twiss()

####################################################
# Tunes, chromaticities, and knobs before matching #
####################################################

# Initial tune and chromaticity values
print(f"Qx = {tw_before['qx']:.5f} Qy = {tw_before['qy']:.5f} "
      f"Q'x = {tw_before['dqx']:.5f} Q'y = {tw_before['dqy']:.5f}")

# Initial value of the knobs correcting tunes an chromaticities
print(f"kqtf.b1 = {line.vars['kqtf.b1']._value}")
print(f"kqtd.b1 = {line.vars['kqtd.b1']._value}")
print(f"ksf.b1 = {line.vars['ksf.b1']._value}")
print(f"ksd.b1 = {line.vars['ksd.b1']._value}")

#####################################################
# Match tunes and chromaticities to assigned values #
#####################################################

line.match(
    vary=[
        xt.Vary('kqtf.b1', step=1e-8),
        xt.Vary('kqtd.b1', step=1e-8),
        xt.Vary('ksf.b1', step=1e-8),
        xt.Vary('ksd.b1', step=1e-8),
    ],
    targets = [
        xt.Target('qx', 62.315, tol=1e-4),
        xt.Target('qy', 60.325, tol=1e-4),
        xt.Target('dqx', 10.0, tol=0.05),
        xt.Target('dqy', 12.0, tol=0.05)])

###################################################
# Tunes, chromaticities, and knobs after matching #
###################################################

tw_final = line.twiss()
print(f"Qx = {tw_final['qx']:.5f} Qy = {tw_final['qy']:.5f} "
      f"Q'x = {tw_final['dqx']:.5f} Q'y = {tw_final['dqy']:.5f}")
print(f"kqtf.b1 = {line.vars['kqtf.b1']._value}")
print(f"kqtd.b1 = {line.vars['kqtd.b1']._value}")
print(f"ksf.b1 = {line.vars['ksf.b1']._value}")
print(f"ksd.b1 = {line.vars['ksd.b1']._value}")

#####################################
# Match with specific twiss options #
#####################################

# Any argument accepted by the twiss method can be passed to the match method
# For example, to match the tunes and chromaticities using the '4d' method:

line.match(method='4d', # <-- 4d matching
    vary=[
        xt.Vary('kqtf.b1', step=1e-8),
        xt.Vary('kqtd.b1', step=1e-8),
        xt.Vary('ksf.b1', step=1e-6),
        xt.Vary('ksd.b1', step=1e-6),
    ],
    targets = [
        xt.Target('qx', 62.29, tol=1e-4),
        xt.Target('qy', 60.31, tol=1e-4),
        xt.Target('dqx', 6.0, tol=0.05),
        xt.Target('dqy', 4.0, tol=0.05)],
    )


##############################################
# Match custom function of the twiss results #
##############################################

# The match method can also be used to match any user-defined function of
# the twiss results. For example, to match the difference between the tunes,
# instead of the vertical tune:

line.match(
    vary=[
        xt.Vary('kqtf.b1', step=1e-10),
        xt.Vary('kqtd.b1', step=1e-10),
        xt.Vary('ksf.b1', step=1e-10),
        xt.Vary('ksd.b1', step=1e-10),
    ],
    targets = [
        xt.Target('qx', 62.27, tol=1e-4),
        xt.Target(lambda tw: tw['qx'] - tw['qy'], 1.98, tol=1e-4), # equivalent to ('qy', 60.325)
        xt.Target('dqx', 6.0, tol=0.05),
        xt.Target('dqy', 4.0, tol=0.05),])

Match an orbit bump

See also xtrack.Line.match()

The match method can also be used with targets at specific locations in the line.

import json

import numpy as np
import xtrack as xt
import xobjects as xo

with open('../../test_data/hllhc14_no_errors_with_coupling_knobs/line_b1.json',
            'r') as fid:
    dct = json.load(fid)
line = xt.Line.from_dict(dct)

line.build_tracker()

tw_before = line.twiss()

line.match(
    # Portion of the beam line to be modified and initial conditions
    ele_start='mq.33l8.b1',
    ele_stop='mq.23l8.b1',
    twiss_init=tw_before.get_twiss_init(at_element='mq.33l8.b1'),
    # Dipole corrector strengths to be varied
    vary=[
        xt.Vary(name='acbv30.l8b1', step=1e-10),
        xt.Vary(name='acbv28.l8b1', step=1e-10),
        xt.Vary(name='acbv26.l8b1', step=1e-10),
        xt.Vary(name='acbv24.l8b1', step=1e-10),
    ],
    targets=[
        # I want the vertical orbit to be at 3 mm at mq.28l8.b1 with zero angle
        xt.Target('y', at='mb.b28l8.b1', value=3e-3, tol=1e-4, scale=1),
        xt.Target('py', at='mb.b28l8.b1', value=0, tol=1e-6, scale=1000),
        # I want the bump to be closed
        xt.Target('y', at='mq.23l8.b1', value=tw_before['y', 'mq.23l8.b1'],
                  tol=1e-6, scale=1),
        xt.Target('py', at='mq.23l8.b1', value=tw_before['py', 'mq.23l8.b1'],
                  tol=1e-7, scale=1000),
    ]
)
_images/orbit_bump.png

The matched orbit bump. The green vertical lines mark the range used For the matching. The red line is the point where the position and angle are imposed. The grey lines mark the location of the used orbit correctors. See the full code generating the image.