Table Of Contents

Previous topic

A first example: fodo_simple1

Next topic


This Page

Using an internal lattice definition: fodo_simple2

This example differs from A first example: fodo_simple1 only in the way the lattice is defined. Instead of reading from a lattice file, we define the lattice file directly in Synergia.

The simulation itself is defined by the Python script

# !/usr/bin/env synergia
import synergia

from import Four_momentum, Reference_particle, pconstants
from synergia.lattice import Lattice_element, Lattice, Mad8_adaptor_map
from synergia.bunch import Bunch, Diagnostics_basic 
from synergia.simulation import Independent_stepper_elements, Bunch_simulator, \

# Set the lattice element parameters
focus_length = 7  # meters
quad_sep = 10  # meters
quad_length = 2.0  # meters
strength = 1.0 / (focus_length * quad_length)  # 1/meters^2

# Define the lattice elements
o = Lattice_element("drift", "o")
o.set_double_attribute("l", quad_sep - quad_length)
f = Lattice_element("quadrupole", "f")
f.set_double_attribute("l", quad_length)
f.set_double_attribute("k1", strength)
d = Lattice_element("quadrupole", "d")
d.set_double_attribute("l", quad_length)
d.set_double_attribute("k1", -strength)

# Define the fodo lattice itself, interpreting elements
# by their Mad8 definitions
lattice = Lattice("fodo", Mad8_adaptor_map())
# Add copies of the lattice elements to the fodo lattice

# Define a reference particle
total_energy = 1.5  # GeV
four_momentum = Four_momentum(pconstants.proton_mass, total_energy)
reference_particle = Reference_particle(pconstants.proton_charge,

# Define a set of simulation steps
map_order = 1
steps_per_element = 2
stepper = Independent_stepper_elements(lattice, map_order, steps_per_element)

# Define a bunch
x_emit = 1.0e-6  # m-rad, RMS
y_emit = 1.0e-6  # m-rad, RMS
z_std = 0.01  # m
dpop = 1.0e-4  # unitless, RMS \frac{\delta p}{p_{tot}}
real_particles = 1.2e12  # unitless, meaningless in this simulation
                         #           without collective effects
macro_particles = 50000
seed = 1415926  # random number seed; 0 for automatic calculation (GSL)
bunch = synergia.optics.generate_matched_bunch_transverse(
              x_emit, y_emit, z_std, dpop,
              real_particles, macro_particles,

# Define a bunch simulator
bunch_simulator = Bunch_simulator(bunch)

# Define a set of bunch diagnostics
# Apply basic diagnostics every step
diagnostics = Diagnostics_basic("diagnostics.h5")

# Perform the simulation
propagator = Propagator(stepper)
turns = 1  # a single pass through the line, since this isn't a ring
max_turns = 0 # Number of turns to run before writing checkpoint and stopping
              # When max_turns is 0, the simulation continues until the end.
verbosity = 2  # Display information about each simulation step
propagator.propagate(bunch_simulator, turns, max_turns, verbosity)

Lattice element definitions

The Synergia Lattice_element class contains a general set of information about an element. Each element has a name, a type, a set of attributes with numerical values and a set of attributes with string values. Here we define focusing and defocusing quadrupoles (f and d, respectively) and a drift (o) with length and strength parameters as used in Mad8.

Lattice definition

The lattice element parameters are only given meaning when they are converted into an internal implementation representation through an Element_adaptor. When we define the Lattice, we give a name for the lattice and an object of type Element_adaptor_map, which contains a mapping from element types to objects of type Element_adaptor. Here we tell the lattice that the elements are to be interpreted as Mad8 elements by passing it an object of type Mad8_adaptor_map. There are built-in adaptor maps for Mad8 and MadX elements. The adaptor maps can be extended to accommodate new element types, or modified to change the implementation behavior of elements.

The Lattice class contains an ordered list of elements. Each element is unique. The uniqueness is enforced by storing a copy a copy of an element when it is appended to the lattice. This means that modifying, say, the f object after it is appended to the lattice will not affect the f in the lattice itself. It also means that the lattice contains two different drifts named “o”. (In practice, it would have been better to name the first drift “o1” and the second drift “o2”.

Reference particle definition

In the beam energy was defined by the BEAM statement. Within Synergia, the Lattice class contains an object of type Reference_particle. Dealing with the various relations between relativistic velocity, momentum and energy is made simpler by the use of the Four_momentum class, which does all the relevant conversions.

Remaining definitions and execution

Now that the lattice object has been properly defined, the remainder of the example is exactly the same as A first example: fodo_simple1.