Skip to content

Advanced topics

Sajid Ali edited this page Oct 19, 2022 · 1 revision

Here some advanced topics for Synergia simulation.

Lattice_simulator

Lattice_simulator provides a set of utility functions to analyze and tune a lattice. Different from Synergia2 in which the same named Lattice_simulator being a class, the Lattice_simulator in Synergia3 is merely a submodule or a namespace which contains a set of free functions. It means that you don't have to create an instance of a Lattice_simulator object from the lattice, but rather call each function with the Lattice object as an argument.

Here are some commonly used Lattice_simulator functions.

  • Closed orbit
# dpp is the delta momentum in calculating the closed orbit, default 0.0
Lattice_simulator.calculate_closed_orbit(lattice, dpp = 0.0)

# set/get the tolerance in calculating the closed orbit
# defaulted to 1e-13
Lattice_simulator.set_closed_orbit_tolerance(tolerance)
Lattice_simulator.get_closed_orbit_tolerance()
  • Tune lattice and set the RF cavities
# tune the RF cavities of a linear lattice
Lattice_simulator.tune_linear_lattice(lattice)

# tune the RF cavities of a circular lattice.
# The difference with above method is that a closed orbit is calculated
# first before tuning a circular lattice
Lattice_simulator.tune_circular_lattice(lattice)
  • Tunes and chromaticities
# calculate the x-y tunes and cdt of a lattice
Lattice_simulator.calculate_tune_and_cdt(lattice, dpp = 0.0)

# adjust the tunes of a lattice to the target h_tune and v_tune
# It requires certain elements in the lattice to be set as the 
# {h|v}_tune_corrector elements, by calling 
#     Lattice_element.set_marker(marker)
# 
Lattice_simulator.adjust_tunes(lattice, 
        horizontal_tune, vertical_tune, 
        tolerance = 1e-5)

# get the chromaticities of a lattice
# The returned object is a combined struct for slip_factor, slip_factor_prime,
# momentum_compaction, horizontal_chromaticity, vertical_chromaticity,
# horizontal_chromaticity_prime, and vertical_chromaticity_prime
Lattice_simulator.get_chromaticities(lattice, dpp = 1e-5)

# adjust the chromaticity of the lattice to the target {h|v}_chromaticity
# Similar to the adjust_tunes(), it requires certain elements to be marked
# as {h|v}_chrom_corrector for it work properly
Lattice_simulator.adjust_chromaticities(lattice, 
        horizontal_chromaticity, vertical_chromaticity, 
        tolerance = 1e-4, max_steps = 6)

# during the calculation of tunes and chromaticities the closed orbit
# of the lattice will be calculated multiple times. The tolerance of
# the closed orbit calculation is also set by the following function.
# If the above methods complains about the tolerance is too tight, you
# may loose it up and try again.
Lattice_simulator.set_closed_orbit_tolerance(tolerance)
  • One turn map
# linear one turn map of arbitrary order (up to 7)
# returns an array of [6][6]
Lattice_simulator.get_linear_one_turn_map(lattice, order)

# Full one turn map from order 1 (_o1) to 7 (_o7)
# returns a full trigon mapping for all 6 components
Lattice_simulator.get_one_turn_map_o1(lattice, dpp = 0.0)
Lattice_simulator.get_one_turn_map_o2(lattice, dpp = 0.0)
...
Lattice_simulator.get_one_turn_map_o7(lattice, dpp = 0.0)
  • Lattice functions

  • Normal form calculation

Spectator Particles

Spectator particles are those that do not contribute to the collective effects of the bunch, yet still affected by the external fields. A properly positioned spectator particle can serve as an observer without affecting the propagation of the actual bunch.

It is possible to create a Bunch object in Synergia3 with certain number of spectator particles.

# total_spectator_num is the number of spectator particles to include in the bunch
bunch = synergia.bunch.Bunch(reference_particle, total_num, real_num,
        comm = Commxx(), total_spectator_num = 0)

# or create a bunch with Bunch_simulator
sim = synergia.simulation.Bunch_simulator(reference_particle, num_particles,
        num_real_particles, commxx = Commxx(), num_spectators = 0)
bunch = sim.get_bunch()

The number of the spectator particles and the actual spectator particle array can be accessed with,

# ParticleGroup is an enum type defined in synergia.bunch.ParticleGroup
#     enum ParticleGroup { regular, spectator }
bunch.size(ParticleGroup.spectator)

# local number (valid spectator particles in local rank)
bunch.get_local_num(ParticleGroup.spectator)

# get the spectator particles array in numpy so they maybe inspected
bunch.get_particles_numpy(ParticlesGroup.spectator)

For syncing particle data between the host and device memory, the checkin_particles() and the checkout_particles() methods need to be called for regular particles and spectator particles respectively,

# the default parameter only copies the regular particles
bunch.checkin_particles()
bunch.checkout_particles()

# sync the spectator particles
bunch.checkin_particles(ParticleGroup.spectator)
bunch.checkout_particles(ParticleGroup.spectator)

Create diagnostics for spectator particles.

Diagnostics support for spectator particles are on a per-diagnostics basis. So far we have the Diagnostics_particles and Diagnostics_bulk_track that support spectator particles. More diagnostics support for the spectator particles will be added as needed.

  • Diagnostics_particles

To write out the spectator particle data, you may construct the diagnostics with following arguments,

# create the diagnostics object
#   num_part:      the number of regular particles 
#                  -1 for all particles, 0 to exclude, default to -1
#   offset:        offset of the first regular particle id, default to 0
#
#   num_spec_part: number of spectator particles
#                  -1 for all particles, 0 to exclude, default to 0
#   spec_offset:   offset of the first spectator particle id, default to 0
diag = Diagnostics_particles(filename, num_part, offset, num_spec_part, spec_offset)

# then register the diag to the Bunch_simulator
simulator.reg_diag_per_turn(diag)
  • Diagnostics_bulk_track

Write out the track data for a series of (regular or spectator) particles

# create the diagnostics object
#   num_tracks:    number of tracked tracks
#   offset:        offset of the first particle to be tracked
#   particlegroup: enum type to indicate whether this is to track the regular particles
#                  or the spectator particles. Defaults to ParticleGroup.regular
diag = Diagnostics_bulk_track(filename, num_tracks, offset, particlegroup)

# then register the diag to the Bunch_simulator
simulator.reg_diag_per_turn(diag)

Bunch Particle Array Layout

Propagate Actions

TBA

Diagnostics and Custom Diagnostics

TBA

Longitudinal Boundaries

A bunch can be set to one of the four different types of longitudinal boundary conditions,

class LongitudinalBoundary(Enum):
    open = 0
    periodic = 1
    aperture = 2
    bucket_barrier = 3

The default longitudinal boundary condition of a bunch is set to LongitudinalBoundary.open. User can set/get the boundary condition using,

Bunch.set_longitudinal_boundary(boundary, param = 0.0)
Bunch.get_longitudinal_boundary()

The param argument to the set method sets the parameter associated to the corresponding boundary condition. Meanings of the param are,

LongitudinalBoundary.open => param ignored
LongitudinalBoundary.periodic => param = z-periodic length
LongitudinalBoundary.aperture => param = z-cut aperture length
LongitudinalBoundary.bucket_barrier => param = bucket length

The get method returns a tuple of [LongitudinalBoundary, float] representing the current longitudinal boundary condition and the parameter associated with it.

If a longitudinal boundary other than the open is set to a bunch, the corresponding boundary action will be performed at the end of each operator on every particle (both regular and spectator) of the bunch.

  • LongitudinalBoundary.periodic applies the z-periodic condition if a particle goes beyond the given periodic length.

  • LongitudinalBoundary.aperture discards the particle which goes beyond the given z-cut length.

  • LongitudinalBoundary.bucket_barrier bounces back the particle with a flipped longitudinal momentum if it goes beyond the z-bucket length.

A diagnostics for the z-cut aperture loss particles can be registered to a bunch to record the location and state of the loss particles due to the Longitudinal.aperture boundary.

Bunch.set_diag_loss_zcut(filename)

Bunch Injection

TBA

Bunch Train and Multiple Bunch Simulation

TBA

Trigon and Mappings

TBA

Dynamic Lattice

TBA