# Example 004: Undulators Plus Bending Magnets¶

In this example the electron trajectory in a mock-straight section is calculated and plotted. The straight section consists of two undulators, an upstream bending magnet and a downstream bending magnet.

In [1]:
# This has nothing to do with OSCARS, but it puts the matplotlib plots inline in the notebook
%matplotlib inline

# Import the OSCARS SR module
import oscars.sr

# Import basic plot utilities (matplotlib).  You don't need these to run OSCARS, but it's used here for basic plots
from oscars.plots_mpl import *

OSCARS v2.1.8 - Open Source Code for Advanced Radiation Simulation
Brookhaven National Laboratory, Upton NY, USA
http://oscars.bnl.gov
oscars@bnl.gov

In [2]:
# Create a new OSCARS object.  Default to 8 threads and always use the GPU if available


## Create the undulator and Bending Magnet Fields¶

Here we create the undulator fields and Bending Magnet fields.

For the undulator, bfield represents maximum magnetic field [$B_x, B_y, B_z$]. The period is also in vector form which allows you to orient the axis of the undulator in any arbitrary direction. The number of periods is given by nperiods. This is the number of FULL periods. A terminating field of 1 period length is added to each side in addition to nperiods.

For the dipole (uniform field) bfield represents the magnetic field [$B_x, B_y, B_z$]. The width is also in vector form which allows you to specify the spatial extent of the uniform field. If one component is zero then that spatial dimension is ignored (the field extends to $\pm \infty$ in that dimension).

Typically clear_magnetic_fields() is called before adding a field in notebooks only to save time when making changes and rerunning sections of the code so it is not strictly necessary.

The undulators and dipoles are placed in space using the translate option.

In [3]:
# Clear any existing fields (just good habit in notebook style) and add an undulator field
osr.clear_bfields()
dist_between_centers = 0.049*15

name='Undulator_1',
bfield=[0, 1, 0],
period=[0, 0, 0.049],
nperiods=21,
translation=[0, 0, -dist_between_centers]
)

name='Undulator_2',
bfield=[0, 1, 0],
period=[0, 0, 0.049],
nperiods=21,
translation=[0, 0, +dist_between_centers]
)

osr.add_bfield_uniform(name='BM_1', bfield=[0, -0.4, 0], width=[0, 0, 0.5], translation=[0, 0, -2])
osr.add_bfield_uniform(name='BM_2', bfield=[0, -0.4, 0], width=[0, 0, 0.5], translation=[0, 0, +2])

In [4]:
# Just to check the field that we added seems visually correct
plot_bfield(osr, -2, 2)

In [5]:
osr.print_bfields()

*Magnetic Fields*
TFieldContainer has 4 fields
TField3D_IdealUndulator
Name                    Undulator_1
Field                   (0, 1, 0)
Period                  (0, 0, 0.049)  (0.049 [m])
NPeriods                21
Center                  (0, 0, -0.735)
Phase                   0
Taper                   0
Frequency               0
FrequencyPhase          0
TimeOffset              0

TField3D_IdealUndulator
Name                    Undulator_2
Field                   (0, 1, 0)
Period                  (0, 0, 0.049)  (0.049 [m])
NPeriods                21
Center                  (0, 0, 0.735)
Phase                   0
Taper                   0
Frequency               0
FrequencyPhase          0
TimeOffset              0

TField3D_UniformBox
Name                BM_1
Field               (0, -0.4, 0)
Width               (0, 0, 0.5)
Rotations           (0, 0, 0)
Center              (0, 0, -2)
Frequency           0
FrequencyPhase      0
TimeOffset          0

TField3D_UniformBox
Name                BM_2
Field               (0, -0.4, 0)
Width               (0, 0, 0.5)
Rotations           (0, 0, 0)
Center              (0, 0, 2)
Frequency           0
FrequencyPhase      0
TimeOffset          0



Here we add a particle beam making use of some of the defaults, namely:

* type='electron'
* t0=0
* x0=[0, 0, 0]
* d0=[0, 0, 1]



One must specify ctstartstop. This is the start and stop time of the calculation. In this example we will start the calculation at t=0 and go to t=2 (given in units of ct) since the beam is relativistic. In this example you can specify the start time as less than 0 which is useful if you want to propogate the particle backwars in time. This is useful for instance if you have a bending magnet before the undulator that you wish to include.

clear_particle_beams() is called, again for convenience, but it is not necessary.

In [6]:
# Setup beam similar to NSLSII
osr.clear_particle_beams()
osr.set_particle_beam(energy_GeV=3, current=0.500)

# Set the start and stop times for the calculation
osr.set_ctstartstop(-1.8, 1.8)


## Calculate Trajectory¶

Now we calculate the trajectory and plot it. It is enough to call calculate_trajectory(). If you are doing other calculations (flux, spectra, power density) it is not necesary to call this since it is called internally.

In [7]:
# Run the particle trajectory calculation
trajectory = osr.calculate_trajectory()

# Plot the trajectory position and velocity
plot_trajectory_position(trajectory)
plot_trajectory_velocity(trajectory)