In [1]:
"""
Example 12
- EEHG (echo enhanced harmonic generation) FEL
- 3-stage simulation: 1st/2nd modulator, 3rd radiator
"""
import sys
isjupyter = "ipykernel" in sys.modules
import simplex
if isjupyter:
simplex.Start(mode="c")
import plotly.io as pio
pio.renderers.default = "notebook" # to enable exporting as an HTML file
from IPython.display import display, HTML
else:
simplex.Start()
# open "sample_mod.json" to simulate the particle motion in the modulator 1&2
simplex.Open("sample_mod.json")
# reduce the bunch charge and length
simplex.Set("ebeam", "bunchleng", 5e-6)
simplex.Set("ebeam", "bunchcharge", 0.05)
# reduce the seed power
simplex.Set("seed", "pkpower", 5e7)
# increase particles/beamlet to cover up to 50th harmonic
simplex.Set("condition", "particles", 102)
# shrink the simulation temporal window
simplex.Set("condition", "simrange", [-12e-6,12e-6])
# dump the particle data at the final step
simplex.Set("datadump", "particle", True)
simplex.Set("datadump", "expstep", "Final Step")
# start simulation in the 1st modulator
simplex.StartSimulation(folder="./output", prefix="sample12", serial=1)
# verify the energy modulation
if isjupyter:
display(HTML("<h2>Particle distribution at the 1st modulator exit with R<sub>56</sub>=5mm"))
simplex.PostProcessCLI.RunDataProcessing(
item="Particle Motion", timerange="Set Window", timewindow=[0, 0], r56pp=8.4e-3,
config={"type":"Symbol", "size":1})
else:
simplex.PostProcess.SetDataProcessing("item", "Particle Motion")
simplex.PostProcess.SetDataProcessing("timerange", "Set Window")
simplex.PostProcess.SetDataProcessing("timewindow", [0, 0])
simplex.PostProcess.SetDataProcessing("r56pp", 8.4e-3)
simplex.PostProcess.RunDataProcessing()
simplex.PostProcess.SymbolPlot(1)
simplex.PostProcess.DuplicatePlot("Particle distribution at the 1st modulator exit with R<sub>56</sub>=5mm")
# 2nd modulator
# import the particle data at the 1st modulator exit with R56=8.4mm
simplex.Set("condition", "simoption", "N.A.") # disable any option to enable importing SIMPLEX output (next command)
simplex.Set("ebeam", "bmprofile", "SIMPLEX Output")
simplex.Set("ebeam", "r56", 8.4e-3)
simplex.Set("spxout", "spxfile", "./output/sample12-1.json")
simplex.Set("seed", "pkpower", 5e6)
simplex.Set("seed", "timing", -4)
# start simulation in the 2nd modulator
simplex.StartSimulation(folder="./output", prefix="sample12", serial=2)
# verify the energy modulation
if isjupyter:
display(HTML("<h2>Particle distribution at the 2nd modulator exit with R<sub>56</sub>=0.24mm"))
simplex.PostProcessCLI.RunDataProcessing(r56pp=3.6e-4, config={"type":"Symbol", "size":1})
else:
simplex.PostProcess.SetDataProcessing("r56pp", 3.6e-4)
simplex.PostProcess.RunDataProcessing()
simplex.PostProcess.SymbolPlot(1)
simplex.PostProcess.DuplicatePlot("Particle distribution at the 2nd modulator exit with R<sub>56</sub>=0.24mm")
# open "sample_rad.json" to simulate the harmonic generation in the radiator
simplex.Open("sample_rad.json")
# import the simulation result at the 2nd modulator exit
simplex.Set("ebeam", "bmprofile", "SIMPLEX Output")
simplex.Set("spxout", "spxfile", "./output/sample12-2.json")
# shorte period and more segments for higher harmonics
simplex.Set("undulator", "lu", 30)
simplex.Set("undulator", "segments", 8)
# enable "Higher Precision" to evaluate the bunch factor more precisely
# needed because the beamlet expands across a large number of slices
simplex.Set("condition", "hpcond", True)
simplex.Set("condition", "step", 10)
# shrink the simulation temporal window
simplex.Set("condition", "simrange", [-5e-6,5e-6])
harmonics = [24, 48] # evaluate the 25th and 50th harmonics
nr = 5 # number of R56 scan for each harmonics
r56 = [3.3e-4, 3.7e-4] # scan R56 from 330um to 370um
fr = 0.01 # spectral range (+-1%) to show
for harmonic in harmonics:
simplex.Set("felprm", "l1st", 266/harmonic)
simplex.Scan("ebeam", "r56", r56[0], r56[1], nr, folder="./output", prefix="sample12", serial=harmonic)
datanames = []
enh = 1240/266*harmonic # central photon energy
for sn in range(1, nr):
datanames.append("sample12-"+str(harmonic)+"_"+str(sn))
if isjupyter:
display(HTML("<h2>Spectrum of "+str(harmonic)+"th-harmonic radiation"))
simplex.PostProcessCLI.Plot(data=["sample12-"+str(harmonic)+"_0", *datanames], item="Spectral Profile",
config={"xrange":[enh*(1-fr),enh*(1+fr)]})
else:
simplex.PostProcess.SelectData("sample12-"+str(harmonic)+"_0")
simplex.PostProcess.Plot("Spectral Profile")
simplex.PostProcess.ComparativePlot(*datanames)
simplex.PostProcess.PlotRange(x=[enh*(1-fr),enh*(1+fr)])
simplex.PostProcess.SetSlide(-1)
simplex.PostProcess.DuplicatePlot("Spectrum of "+str(harmonic)+"th-harmonic radiation")
if not isjupyter:
input("Completed. Press enter to exit. ")
simplex.Exit()