This notebook was created by Sergey Tomin (sergey.tomin@desy.de). Source and license info is on GitHub. April 2020.

An Introduction to Ocelot

Ocelot is a multiphysics simulation toolkit designed for studying FEL and storage ring based light sources. Ocelot is written in Python. Its central concept is the writing of python's scripts for simulations with the usage of Ocelot's modules and functions and the standard Python libraries.

Ocelot includes following main modules:

  • Charged particle beam dynamics module (CPBD)
    • optics
    • tracking
    • matching
    • collective effects (description can be found here and here)
      • Space Charge (3D Laplace solver)
      • CSR (Coherent Synchrotron Radiation) (1D model with arbitrary number of dipoles).
      • Wakefields (Taylor expansion up to second order for arbitrary geometry).
    • MOGA (Multi Objective Genetics Algorithm) ref.
  • Native module for spontaneous radiation calculation (some details can be found here and here)
  • FEL calculations: interface to GENESIS and pre/post-processing
  • Modules for online beam control and online optimization of accelerator performances. ref1, ref2, ref3, ref4.
    • This module is being developed in collaboration with other accelerator groups. The module has been migrated to a separate repository (in ocelot-collab organization) for ease of collaborative development.

Ocelot extensively uses Python's NumPy (Numerical Python) and SciPy (Scientific Python) libraries, which enable efficient in-core numerical and scientific computation within Python and give you access to various mathematical and optimization techniques and algorithms. To produce high quality figures Python's matplotlib library is used.

It is an open source project and it is being developed by physicists from The European XFEL, DESY (Germany), NRC Kurchatov Institute (Russia).

We still have no documentation but you can find a lot of examples in /demos/ folder including this tutorial

Ocelot user profile

Ocelot is designed for researchers who want to have the flexibility that is given by high-level languages such as Matlab, Python (with Numpy and SciPy) or Mathematica. However if someone needs a GUI it can be developed using Python's libraries like a PyQtGraph or PyQt.

For example, you can see GUI for SASE optimization (uncomment and run next block)


In [4]:
from IPython.display import Image
# Image(filename='gui_example.png')

Tutorials

  • Preliminaries: Setup & introduction

Beam dynamics

Photon field simulation

Appendixes

Preliminaries

The tutorial includes 7 simple examples dedicated to beam dynamics and optics. However, you should have a basic understanding of Computer Programming terminologies. A basic understanding of Python language is a plus.

This tutorial requires the following packages:

Optional to speed up python

  • numexpr (version 2.6.1)
  • pyfftw (version 0.10)
  • numba

Orbit Correction module

  • pandas

The easiest way to get these is to download and install the Anaconda software distribution.

Alternatively, you can download and install miniconda. The following command will install all required packages:

$ conda install numpy scipy matplotlib jupyter

Ocelot installation

Anaconda Cloud

The easiest way to install OCELOT is to use Anaconda cloud. In that case use command:

```
$ conda install -c ocelot-collab ocelot
```
Explicit installation

Another way is download ocelot from GitHub

  1. you have to download from GitHub zip file.
  2. Unzip ocelot-master.zip to your working folder /your_working_dir/.
  3. Add ../your_working_dir/ocelot-master to PYTHONPATH

    • Windows 7: go to Control Panel -> System and Security -> System -> Advance System Settings -> Environment Variables. and in User variables add /your_working_dir/ocelot-master/ to PYTHONPATH. If variable PYTHONPATH does not exist, create it

      Variable name: PYTHONPATH

      Variable value: ../your_working_dir/ocelot-master/

    • Linux:
      $ export PYTHONPATH=/your_working_dir/ocelot-master:$PYTHONPATH

To launch "ipython notebook" or "jupyter notebook"

in command line run following commands:

$ ipython notebook

or

$ ipython notebook --notebook-dir="path_to_your_directory"

or

$ jupyter notebook --notebook-dir="path_to_your_directory"

Checking your installation

You can run the following code to check the versions of the packages on your system:

(in IPython notebook, press shift and return together to execute the contents of a cell)


In [6]:
import IPython
print('IPython:', IPython.__version__)

import numpy
print('numpy:', numpy.__version__)

import scipy
print('scipy:', scipy.__version__)

import matplotlib
print('matplotlib:', matplotlib.__version__)

import ocelot
print('ocelot:', ocelot.__version__)


IPython: 7.11.1
numpy: 1.18.1
scipy: 1.3.1
matplotlib: 3.1.1
initializing ocelot...
ocelot: 20.04.0

Tutorial N1. Double Bend Achromat.

We designed a simple lattice to demonstrate the basic concepts and syntax of the optics functions calculation. Also, we chose DBA to demonstrate the periodic solution for the optical functions calculation.


In [7]:
from __future__ import print_function

# the output of plotting commands is displayed inline within frontends, 
# directly below the code cell that produced it
%matplotlib inline

# import from Ocelot main modules and functions
from ocelot import *

# import from Ocelot graphical modules
from ocelot.gui.accelerator import *

Creating lattice

Ocelot has following elements: Drift, Quadrupole, Sextupole, Octupole, Bend, SBend, RBend, Edge, Multipole, Hcor, Vcor, Solenoid, Cavity, Monitor, Marker, Undulator.


In [8]:
# defining of the drifts
D1 = Drift(l=2.)
D2 = Drift(l=0.6)
D3 = Drift(l=0.3)
D4 = Drift(l=0.7)
D5 = Drift(l=0.9)
D6 = Drift(l=0.2)

# defining of the quads
Q1 = Quadrupole(l=0.4, k1=-1.3)
Q2 = Quadrupole(l=0.8, k1=1.4)
Q3 = Quadrupole(l=0.4, k1=-1.7)
Q4 = Quadrupole(l=0.5, k1=1.3)

# defining of the bending magnet
B = Bend(l=2.7, k1=-.06, angle=2*pi/16., e1=pi/16., e2=pi/16.)

# defining of the sextupoles
SF = Sextupole(l=0.01, k2=1.5) #random value
SD = Sextupole(l=0.01, k2=-1.5) #random value

# cell creating
cell = (D1, Q1, D2, Q2, D3, Q3, D4, B, D5, SD, D5, SF, D6, Q4, D6,
        SF, D5, SD, D5, B, D4, Q3, D3, Q2, D2, Q1, D1)

In [9]:
cell


Out[9]:
(<ocelot.cpbd.elements.Drift at 0x1c1adf8d90>,
 <ocelot.cpbd.elements.Quadrupole at 0x1c1adf8ed0>,
 <ocelot.cpbd.elements.Drift at 0x1c1ad0cb10>,
 <ocelot.cpbd.elements.Quadrupole at 0x1c1adf8f50>,
 <ocelot.cpbd.elements.Drift at 0x1c1abeaf10>,
 <ocelot.cpbd.elements.Quadrupole at 0x1c1ae06050>,
 <ocelot.cpbd.elements.Drift at 0x1c1adf8d50>,
 <ocelot.cpbd.elements.Bend at 0x1c1ae06190>,
 <ocelot.cpbd.elements.Drift at 0x1c1adf8dd0>,
 <ocelot.cpbd.elements.Sextupole at 0x1c1a941050>,
 <ocelot.cpbd.elements.Drift at 0x1c1adf8dd0>,
 <ocelot.cpbd.elements.Sextupole at 0x1c1ae06210>,
 <ocelot.cpbd.elements.Drift at 0x1c1adf8e50>,
 <ocelot.cpbd.elements.Quadrupole at 0x1c1ae060d0>,
 <ocelot.cpbd.elements.Drift at 0x1c1adf8e50>,
 <ocelot.cpbd.elements.Sextupole at 0x1c1ae06210>,
 <ocelot.cpbd.elements.Drift at 0x1c1adf8dd0>,
 <ocelot.cpbd.elements.Sextupole at 0x1c1a941050>,
 <ocelot.cpbd.elements.Drift at 0x1c1adf8dd0>,
 <ocelot.cpbd.elements.Bend at 0x1c1ae06190>,
 <ocelot.cpbd.elements.Drift at 0x1c1adf8d50>,
 <ocelot.cpbd.elements.Quadrupole at 0x1c1ae06050>,
 <ocelot.cpbd.elements.Drift at 0x1c1abeaf10>,
 <ocelot.cpbd.elements.Quadrupole at 0x1c1adf8f50>,
 <ocelot.cpbd.elements.Drift at 0x1c1ad0cb10>,
 <ocelot.cpbd.elements.Quadrupole at 0x1c1adf8ed0>,
 <ocelot.cpbd.elements.Drift at 0x1c1adf8d90>)

hint: to see a simple description of the function put cursor inside () and press Shift-Tab or you can type sign ? before function. To extend dialog window press + Also, one can get more info about element just using print(element)


In [10]:
print(B)


Bend : id = ID_6257188_
l       =  2.7000 m
angle   =  22.500 deg
e1      =  11.250 deg
e2      =  11.250 deg
tilt    =   0.000 deg
fint    =   0.000
fintx   =   0.000
gap     =  0.0000 m
h_pole1 =  0.0000 1/m
h_pole2 =  0.0000 1/m

The cell is a list of the simple objects which contain a physical information of lattice elements such as length, strength, voltage and so on. In order to create a transport map for every element and bind it with lattice object we have to create new Ocelot object - MagneticLattice() which makes these things automatically.

MagneticLattice(sequence, start=None, stop=None, method=MethodTM()):

  • sequence - list of the elements,

other parameters we will consider in tutorial N2.


In [11]:
lat = MagneticLattice(cell)

# to see total lenth of the lattice 
print("length of the cell: ", lat.totalLen, "m")


length of the cell:  20.34 m

Optical function calculation

Uses:

  • twiss() function and,
  • Twiss() object contains twiss parameters and other information at one certain position (s) of lattice

To calculate twiss parameters you have to run twiss(lattice, tws0=None, nPoints=None) function. If you want to get a periodic solution leave tws0 by default.

You can change the number of points over the cell, If nPoints=None, then twiss parameters are calculated at the end of each element. twiss() function returns list of Twiss() objects.

You will see the Twiss object contains more information than just twiss parameters.

In [12]:
tws = twiss(lat, nPoints=1000)

# to see twiss paraments at the begining of the cell, uncomment next line
# print(tws[0])
print("length = ", len(tws))
# to see twiss paraments at the end of the cell, uncomment next line
print(tws[998] == tws[-1])


length =  1000
False

In [13]:
# plot optical functions.
plot_opt_func(lat, tws, top_plot = ["Dx", "Dy"], legend=False, font_size=10)
plt.show()

# you also can use standard matplotlib functions for plotting
#s = [tw.s for tw in tws]
#bx = [tw.beta_x for tw in tws]
#plt.plot(s, bx)
#plt.show()



In [14]:
# you can play with quadrupole strength and try to make achromat
Q4.k1 = 1.18

# to make achromat uncomment next line
# Q4.k1 =  1.18543769836
# To use matching function, please see ocelot/demos/ebeam/dba.py 

# updating transfer maps after changing element parameters. 
lat.update_transfer_maps()

# recalculate twiss parameters 
tws=twiss(lat, nPoints=1000)

plot_opt_func(lat, tws, legend=False)
plt.show()



In [ ]:


In [ ]:


In [ ]: