-
Notifications
You must be signed in to change notification settings - Fork 4
Advanced topics
Here some advanced topics for Synergia simulation.
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 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)
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)
TBA
TBA
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)
TBA
TBA
TBA
TBA