4d method for twiss and build_particles

When the RF cavities are disabled or not included in the lattice or when the longitudinal motion is artificially frozen, the one-turn matrix of the line is singular, and it is no possible to use the standard method for the twiss calculation and to generate particles distributions matched to the lattice. In these cases, the “4d” method can be used, as illustrated in the following examples:

import json
import numpy as np

import xobjects as xo
import xtrack as xt
import xpart as xp

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

fname_line_particles = '../../test_data/hllhc15_noerrors_nobb/line_and_particle.json'

with open(fname_line_particles, 'r') as fid:
    input_data = json.load(fid)
line = xt.Line.from_dict(input_data['line'])
line.particle_ref = xp.Particles.from_dict(input_data['particle'])

tracker = line.build_tracker()

# We consider a case in which all RF cavities are off
for ee in line.elements:
    if isinstance(ee, xt.Cavity):
        ee.voltage = 0

##################
# Twiss(4d mode) #
##################

# For this configuration, `tracker.twiss()` gives an exception because the
# longitudinal motion is not stable.
# In this case, the '4d' method of `tracker.twiss()` can be used to compute the
# twiss parameters.

tw = tracker.twiss(method='4d')

###########################################
# Match a particle distribution (4d mode) #
###########################################

# The '4d' method can also be used to match a particle distribution:

particles = tracker.build_particles(method='4d',
                    x_norm=[1,2,3,4], # sigmas
                    nemitt_x=2.5e-6, nemitt_y=2.5e-6)