Adding lattice elements
Lattice elements for applied fields to focus, accelerate, and bend the beam (and/or the coordinate system) can be added using using Lattice Element Scripts, MAD Style Input, or by Directly Setting Lattice Arrays that the code uses. These are outlined below. Warp users are encouraged to use the lattice element scripts as a first option. Mad style input is retained for legacy compatibility and directly setting lattice arrays used by the code should be reserved for special cases by expert users. Most classes of lattice elements have many possible options and are compatible with ring (multiple pass) and linear (single pass) architecture machines. For rings, periodicity variables should be consistently set.
More information on this topic can also be found in the lattice documentation. For time dependent lattice elements, see Time dependent lattice elements.
Lattice Element Scripts
To simplify the process of adding lattice elements, python functions are available that set the appropriate Warp variables to add elements to the simulation. These functions are recommended as the preferred method to construct a lattice. For each type of lattice element, there is a corresponding function addnewelemement() with "element" replaced with the class of lattice element. For example:
addnewquad(zs=...,ze=...,db=...)
adds a new "hard-edged" magnetic quadrupole lattice element with axial start coordinate z= zs in the lattice, end coordinate z = ze, and linear field gradient db = d By/dx = const as specified from z = zs to z = ze. Similarly,
addnewquad(zs=...,ze=...,de=...)
adds a new hard-edge electric quadrupole lattice element with linear field gradient de = d Ex/dx = const. Generally, the addnewelement() functions must be called with at least zs and ze and other arguments are optional. Numerous options exist to offset, tilt, rotate, and specify details of the elements. Details can be found with doc(addnewquad), etc. The functions can be called at any time and in any order. Setting up the lattice can become complicated. For example, if there is a misaligned non-ideal magnet in a ring, the lattice fields of this specific non-ideal magnet (which may also break period symmetry in the lattice making up the ring) should be encountered once per lap as the beam cycles the ring.
Alternatively to these scripts, the relevant lattice arrays that Warp employs and the lattice element scripts set can be sized appropriately and set as desired as described below under Directly Setting Lattice Arrays. However, this can become complicated due to the general nature of the problem and should only be applied in special cases by expert code users.The complexity results from lattice element arrays needing to be sufficiently general to cover cases such as periodic errors in rings.
Available addnewelement() functions for creating lattice elements include:
addnewdrft(...) # Drift element (can be used to load aperture/pipe structure in some field solvers)
addnewquad(...) # Hard-edged or self-consistent quadrupole (magnetic or electric) focusing elements
addnewbend(...) # Bending lattice elements
addnewdipo(...) # Hard-edged or self-consistent dipole bending elements
addnewaccl(...) # Hard-edged accelerating gaps
addnewsext(...) # Hard-edged sextupole elements
addnewhele(...) # Hard-edged arbitrary electric and magnetic multipole moments
addnewemlt(...) # Axially varying arbitrary electric multipole moments
addnewmmlt(...) # Axially varying arbitrary magnetic multipole moments
addnewbgrd(...) # Magnetic field specified on a two or three-dimensional grid
addnewegrd(...) # Electric field specified on a two or three-dimensional grid
addnewpgrd(...) # Electrostatic potential specified on a two or three-dimensional grid
See individual script documentation for available options. The various addnewelement() functions can be applied to quickly build up detailed and realistic lattice models while simplifying the interfacing issues with the lattice element arrays used by Warp to set the applied fields in the particle advance.
Below we setup a simple hard-edge magnetic FODO quadrupole focusing lattice to illustrate how lattice element scripts can be applied. The FODO lattice has 50% magnetic occupancy and starts at z=0 entering a hard-edge quadrupole with a positive field gradient.
rp = 2.*cm # aperture radius [m]
Bp = 1. # pole tip field at aperture [Tesla]
lq = 20.*cm # Quadrupole hard-edge axial length [m]
ld = 20.*cm # Drift length between hard-edge quadrupoles [m]
dbdx = Bp/rp
addnewquad(zs=0.,ze=lq,db=dbdx,ap=rp)
addnewdrift(zs=lq,ze=lq+ld,ap=rp)
addnewquad(zs=lq+ld,ze=2.*lq+ld,db=-dbdx,ap=rp)
addnewdrift(zs=2.*lq+ld,ze=2.*lq+2.*ld,ap=rp)
This lattice can then be continued periodically by setting lattice periodicity with:.
top.zlatstrt = 0. # z of lattice start (added to element z's on generate).
top.zlatperi = 2.*(lq+ld) # lattice periodicity
The value of top.zlatstart (default zero, shown only to clarify) can be set to manipulate the phase of the periodic lattice. Or equivalently, the initial load/injection location of the beam can be varied in the lattice.
For more detailed electric and magnetic element descriptions such as gridded field elements [egrd,bgrd] and 3d multipole moments [emlt,mmlt] it may be desirable to have several elements in the lattice use a common data file describing the field. In this case, the file data might be entered functions like:
addnewbgrddataset(...) # Add new data set for bgrd applied B-field elements
addnewegrddataset(...) # Add new data set for egrd applied E-field elements
addnewmmltdataset(...) # Add new data set for 3d magnetic multipole moment
addnewemltdataset(...) # Add new data set for 3d electric multipole moment
For example, 3d gridded magnetic field arrays bx, by, bz with transverse grid increments dx, dy, and axial grid length zlen can be loaded into gridded field lattice arrays with
ibgrd = addnewbgrddataset(bx=bx,by=by,bz=bz,dx=dx,dy=dy,zlength=zlen)
and the corresponding unique bgrd data set index ibgrd returned in the call to addnewbrddataset() can then be used to setup optical elements using the same data set in two instances with
addnewbgrd(id=ibgrd,zs=0.,ze=zlen)
addnewbgrd(id=ibgrd,zs =1.,ze=1.+zlen,sc=-1)
Here, we put the first instance of the field array starting at z = 0. and the second instance starting at z = 1. meter with scale factor -1 (all elements in field array flipped) as might be done for a second magnetic quadrupole in an alternating gradient focusing lattice. Transverse x,y mesh coordinates are assumed to start at the simulation mesh bounds w3d.xmmin, w3d.ymmin unless the x- and y- starts of the mesh are passed. Note that the axial extent of the mesh passed in addnewbgrddataset() together with the length of the mesh, which fixes the axial mesh increment dz. But the starts and stops of the field put down in the lattice are specified with addnewbgrd(). A setup like this is natural since the same data may be applied at numerous axial locations in the lattice.Field data can also be modulated in time for pulsed or harmonic effects with input functions as discussed in Time dependent lattice elements. It is often the case for magnetic and rf elements that data for the gridded field may be imported from other codes via data exported/archived in large ascii text files. Details on how such data can be read into Warp with the proper format for use in gridded field elements can be found in the example gridded B-field read presented in the subsection Reading an ASCII Text Data File within Saving/Retrieving Data in External Files. Gridded field elements can also work with symmetry options including r-z (axisymmetric) symmetry and transverse x-y quadrrant quadrupole symmetry for more efficient simulation of ideal solenoid and quadrupole focusing magnets.
Various diagnostic functions are useful to verify that the lattice is loaded correctly. Useful functions to plot applied fields loaded associated with more detailed element descriptions include:
plotmmlt() # Plot magnetic multipole moments
plotemlt() # Plot electric multipole moments
plotacclet() # Plot time dependent fields of an acceleration element
plotbgrd() # Plot components of gridded applied magnetic field element
plotegrd() # Plot components of gridded applied electric field element
In cases where these are not sufficient, or other checks are needed, diagnostics can be constructed by getting the applied fields at a coordinate (or array of coordinates) or on a grid and then using basic plotting and contouring functions to construct desired diagnostics. Useful functions to retrieve the applied field for such diagnostics include:
getappliedfields() # Returns tuple of applied fields (ex,ey,ez,bx,by,bz) at specified position(s) x,y,z
getappliedfieldsongrid() # Analogous to getappliedfields() but on a specified uniform mesh
MAD Style Input
The MAD family of codes (MAD, MAD-X, MAD-8, diMAD, ...) employ a commonly used syntax for lattice descriptions in accelerator physics. Warp has scripts that part replicate this syntax:
Drft() # Create drift instance
Bend() # Create bend instance
Dipo() # Create dipole instance
Quad() # Create quadrupole instance
Sext() # Create sextupole instance
Hele() # Create hard edge multipole moment instance
Accl() # Create acceleration instance
Emlt() # Create electric multipole moment instance
Mmlt() # Create magnetic multipole moment instance
Bgrd() # Create gridded B-field instance
Pgrd() # Create gridded E-field instance
These scripts define an instance of the element class they represent in the lattice. They all take an argument specifying the length of the element. Other arguments define the properties of the field. For example, to define a hard-edge focusing magnetic FODO quadrupole focusing lattice with a period of 20 cm, 50% occupancy, 1.5 Tesla/m magnetic gradient, and a 3 cm aperture radius, we proceed as follows. First we define focusing and defocusing quadruples and a drift with
qf = Quad(l=10.*cm,db= 1.5,ap=3.*cm) # focusing magnetic quadrupole
qd = Quad(l=10.*cm,db=-1.5,ap=3.*cm) # defocusing magnetic quadrupole
dd = Drft(l=5.*cm,ap=3.*cm) # drift
Then we define the lattice period and setup the underlying Warp lattice element arrays used by the code with
lp = qf + dd + qd + dd
madtowarp(lp)
Alternatively, one could then define a section which was 10 of these lattice periods in a row using:
s1 = 10*lp
For an accelerator made up of 3 sections, named s1, s2, and s3, the underlying Warp lattice arrays are setup with:
lattice = s1 + s2 + s3
madtowarp(lattice)
There is also a function to read in MAD style input files to generate a Warp lattice:
getlattice()
Directly Setting Lattice Arrays
In principle, users can directly set variables in the lattice arrays/variables that the code uses to generate the desired lattice. However, it is recommended that the user NOT do this because many quantities must be set consistently to properly function. This also bypasses numerous error checks that the methods in the Lattice Element Scripts or the scripts for MAD Style Input provide. Nevertheless, directly accessing the lattice arrays can be useful for debugging. To understand how to do this, examine variable blocks defined in the source code within top.v. For example,
top.quads # logical variable flagging the existance of quadrupole hard-edge elements
top.quadzs # Array (if allocated) of hard-edge quadrupole z-start coordinates
Many lattice element arrays are dynamic and must, if set, be sized appropriately. For example, if 10 quadrupoles will be defined in the lattice, you should first allocate memory in the dynamic lattice arrays calling:
top.quads = true
top.nquad = 10
gchange("Lattice")
and then set relevant quadrupole lattice arrays defined in top.v to specify the elements. Here, top.quads is set to true so the lattice fields corresponding to the quad lattice element arrays will be set in the applied field gather. If top.quads is not set to true, the corresponding element fields will not be set in the applied field gather. This illustrates a simple case of many potential subtleties and pitfalls associated with directly setting lattice arrays.