Fast electrons - electron energy loss spectroscopy (EELS)

Example authors: A. Arbouet / P. R. Wiecha (electron submodule by A. Arbouet)

!!Attention!!: The electron module is still beta functionality and is to be used with caution.

In this example, we reproduce the results of EELS spectral measurements from Campos et al. [1].

[1]: Campos et al.: Plasmonic Breathing and Edge Modes in Aluminum Nanotriangles ACS Photonics 4(5), 1257 (2017) (

import matplotlib.pyplot as plt
import numpy as np

from pyGDM2 import structures
from pyGDM2 import materials
from pyGDM2 import fields
from pyGDM2 import core
from pyGDM2 import propagators
from pyGDM2 import electron
from pyGDM2 import tools
from pyGDM2 import visu

Eelec = 100.         # electron kinetic energy (keV)
kSign = 1            # Electron propagation direction
xel = 0.             # X beam position in (OXY) plane
yel =  [270, -270]   # Y beam position in (OXY) plane

#         nanostructure
mesh = 'hex'
step = 20

## note: set H=3 for conditions in Campos et al. ACS Photonics 4(5), Pp.1257 (2017)
geometry = structures.prism(step, NSIDE=35, H=2, mesh=mesh, ORIENTATION=1)
geometry = structures.center_struct(geometry)
material = materials.alu()

struct = structures.struct(step, geometry, material)

#         E-Field of fast electron beam
energy = np.linspace(1, 3.5, 41)   # linear energy scale
wavelengths = 1239.0 / energy      # eV --> nm

## --- Defining E-field associated with fast electron beam
field_generator = fields.fast_electron
kwargs = dict(electron_kinetic_energy=Eelec,
              x0=xel, y0=yel, kSign=kSign)

efield = fields.efield(field_generator, wavelengths=wavelengths, kwargs=kwargs)

#         environment (--> used Green's tensors)
n3 = 1.0  # cladding layer
n2 = 1.0  # environment
n1 = 2.0  # substrate environment
spacing = 10000.

dyads = propagators.DyadsQuasistatic123(n1, n2, n3, spacing=spacing)

#         init sim
sim = core.simulation(struct=struct, efield=efield, dyads=dyads)

print("N dipoles:", len(sim.struct.geometry))
structure initialization - automatic mesh detection: hex
structure initialization - consistency check: 1225/1225 dipoles valid
/home/hans/.local/lib/python3.8/site-packages/pyGDM2/ UserWarning: 3D data. Falling back to XY projection...
  warnings.warn("3D data. Falling back to XY projection...")
N dipoles: 1225

run the simulation

Now we run the simulation, calculating EELS spectra at the two indicated positions

## run the simulation
/home/hans/.local/lib/python3.8/site-packages/numba/core/ UserWarning: Numba extension module 'numba_scipy' failed to load due to 'ValueError(No function '__pyx_fuse_0pdtr' found in __pyx_capi__ of 'scipy.special.cython_special')'.
timing for wl=1239.00nm - setup: EE 5373.4ms, inv.: 1401.2ms, repropa.: 833.5ms (2 field configs), tot: 7608.4ms
timing for wl=1166.12nm - setup: EE 2544.5ms, inv.: 3312.4ms, repropa.: 103.8ms (2 field configs), tot: 5961.7ms
timing for wl=1101.33nm - setup: EE 2573.5ms, inv.: 1415.6ms, repropa.: 95.7ms (2 field configs), tot: 4086.0ms
timing for wl=1043.37nm - setup: EE 2543.8ms, inv.: 1325.5ms, repropa.: 115.5ms (2 field configs), tot: 3985.4ms
timing for wl=991.20nm - setup: EE 2544.8ms, inv.: 1429.1ms, repropa.: 87.5ms (2 field configs), tot: 4062.4ms
timing for wl=944.00nm - setup: EE 2538.1ms, inv.: 1207.3ms, repropa.: 89.8ms (2 field configs), tot: 3835.8ms
timing for wl=901.09nm - setup: EE 2549.9ms, inv.: 1231.2ms, repropa.: 104.4ms (2 field configs), tot: 3886.3ms
timing for wl=861.91nm - setup: EE 2558.9ms, inv.: 1170.8ms, repropa.: 92.0ms (2 field configs), tot: 3822.7ms
timing for wl=826.00nm - setup: EE 2542.0ms, inv.: 1215.1ms, repropa.: 91.4ms (2 field configs), tot: 3849.2ms
timing for wl=792.96nm - setup: EE 2573.8ms, inv.: 1276.5ms, repropa.: 94.6ms (2 field configs), tot: 3945.9ms
timing for wl=762.46nm - setup: EE 2559.5ms, inv.: 1148.6ms, repropa.: 102.9ms (2 field configs), tot: 3812.0ms
timing for wl=734.22nm - setup: EE 2541.5ms, inv.: 1167.7ms, repropa.: 88.2ms (2 field configs), tot: 3798.4ms
timing for wl=708.00nm - setup: EE 2544.6ms, inv.: 1115.7ms, repropa.: 90.2ms (2 field configs), tot: 3751.1ms
timing for wl=683.59nm - setup: EE 2570.0ms, inv.: 1143.0ms, repropa.: 87.1ms (2 field configs), tot: 3801.1ms
timing for wl=660.80nm - setup: EE 2565.4ms, inv.: 1162.4ms, repropa.: 93.4ms (2 field configs), tot: 3822.3ms
timing for wl=639.48nm - setup: EE 2569.8ms, inv.: 1202.2ms, repropa.: 86.5ms (2 field configs), tot: 3859.1ms
timing for wl=619.50nm - setup: EE 2569.8ms, inv.: 1190.1ms, repropa.: 87.3ms (2 field configs), tot: 3848.2ms
timing for wl=600.73nm - setup: EE 2583.6ms, inv.: 1257.5ms, repropa.: 87.9ms (2 field configs), tot: 3930.0ms
timing for wl=583.06nm - setup: EE 2581.3ms, inv.: 1338.2ms, repropa.: 87.1ms (2 field configs), tot: 4007.4ms
timing for wl=566.40nm - setup: EE 2561.8ms, inv.: 1241.2ms, repropa.: 108.2ms (2 field configs), tot: 3912.2ms
timing for wl=550.67nm - setup: EE 2577.8ms, inv.: 1166.2ms, repropa.: 87.5ms (2 field configs), tot: 3832.2ms
timing for wl=535.78nm - setup: EE 2544.5ms, inv.: 2607.7ms, repropa.: 248.9ms (2 field configs), tot: 5402.4ms
timing for wl=521.68nm - setup: EE 6872.4ms, inv.: 2918.5ms, repropa.: 87.6ms (2 field configs), tot: 9879.3ms
timing for wl=508.31nm - setup: EE 2528.2ms, inv.: 1172.8ms, repropa.: 87.9ms (2 field configs), tot: 3789.5ms
timing for wl=495.60nm - setup: EE 2560.9ms, inv.: 1156.5ms, repropa.: 98.5ms (2 field configs), tot: 3816.6ms
timing for wl=483.51nm - setup: EE 2549.8ms, inv.: 1239.7ms, repropa.: 89.2ms (2 field configs), tot: 3879.4ms
timing for wl=472.00nm - setup: EE 2545.7ms, inv.: 1200.4ms, repropa.: 89.7ms (2 field configs), tot: 3836.5ms
timing for wl=461.02nm - setup: EE 2576.4ms, inv.: 1391.2ms, repropa.: 88.7ms (2 field configs), tot: 4057.3ms
timing for wl=450.55nm - setup: EE 2553.2ms, inv.: 3009.6ms, repropa.: 244.5ms (2 field configs), tot: 5808.7ms
timing for wl=440.53nm - setup: EE 6743.9ms, inv.: 4119.6ms, repropa.: 89.4ms (2 field configs), tot: 10953.8ms
timing for wl=430.96nm - setup: EE 2522.7ms, inv.: 1668.1ms, repropa.: 102.3ms (2 field configs), tot: 4294.0ms
timing for wl=421.79nm - setup: EE 2611.7ms, inv.: 1720.5ms, repropa.: 96.7ms (2 field configs), tot: 4429.9ms
timing for wl=413.00nm - setup: EE 2546.1ms, inv.: 1662.0ms, repropa.: 100.4ms (2 field configs), tot: 4309.1ms
timing for wl=404.57nm - setup: EE 2555.3ms, inv.: 6164.3ms, repropa.: 247.0ms (2 field configs), tot: 8967.9ms
timing for wl=396.48nm - setup: EE 6694.7ms, inv.: 2886.6ms, repropa.: 93.6ms (2 field configs), tot: 9675.7ms
timing for wl=388.71nm - setup: EE 2521.8ms, inv.: 1694.4ms, repropa.: 97.1ms (2 field configs), tot: 4314.0ms
timing for wl=381.23nm - setup: EE 2578.6ms, inv.: 1793.5ms, repropa.: 103.6ms (2 field configs), tot: 4476.5ms
timing for wl=374.04nm - setup: EE 2583.5ms, inv.: 2107.0ms, repropa.: 247.9ms (2 field configs), tot: 4940.0ms
timing for wl=367.11nm - setup: EE 6777.8ms, inv.: 4362.3ms, repropa.: 241.4ms (2 field configs), tot: 11382.9ms
timing for wl=360.44nm - setup: EE 3155.9ms, inv.: 1888.9ms, repropa.: 114.7ms (2 field configs), tot: 5160.2ms
timing for wl=354.00nm - setup: EE 2500.5ms, inv.: 2507.3ms, repropa.: 117.4ms (2 field configs), tot: 5126.0ms

Plot the EELS spectra

Comparison with the reference gives a very good agreement

#%% EELS spectra
## prism tip
wl, EELS_spec_tip = tools.calculate_spectrum(sim, 0, electron.EELS)
## side center
wl, EELS_spec_side = tools.calculate_spectrum(sim, 1, electron.EELS)

plt.title("EELS spectrum")
plt.plot(energy, EELS_spec_tip, label='e at tip')
plt.plot(energy, EELS_spec_side, label='e at side center')
plt.xlabel("energy (eV)")
plt.ylabel("EELS probability")

Plot cathodoluminescence (CL) spectra

Cathodoluminescence can be calculated as well

## prism tip
wl, CL_spec_tip = tools.calculate_spectrum(sim, 0, electron.CL)
## prism bottom center
wl, CL_spec_side = tools.calculate_spectrum(sim, 1, electron.CL)

plt.title("CL spectrum")
plt.plot(energy, CL_spec_tip, label='e at tip')
plt.plot(energy, CL_spec_side, label='e at side center')
plt.xlabel("energy (eV)")
plt.ylabel("CL intensity (a.u.)")