FDTD 101: Modeling dispersive material in FDTD
Lecture 5: Modeling dispersive material in FDTD
Material dispersion is a very common phenomenon in which the material responds differently to light of different color. In this lecture, we show how to include material dispersion in FDTD simulations.
- Show how to include simple analytical dispersion relations in FDTD, illustrated by an example of simulating surface plasmon polaritonic (SPP) resonance between gold and air interface.
- Introduction to a popular method for describing material dispersion in FDTD, known as the complex-conjugate pole-residue method.
- Show how to include more complicated dispersion relations that need to be inferred from tabulated data, illustrated by an example of simulating crystalline silicon slab transmission with the help of dispersion fitting tools.
For Python setup used in this lecture, please see related FDTD Python Tutorial below.
Tutorial 5: Part 1 -- surface plasmon polariton resonance¶
In this notebook, we show how to include simple analytical dispersion relations. As an detailed example, we will walk you through the simulation of surface plasmon polaritons (SPPs) at the gold-air interface, where the reponse of gold is approximated by the Drude model.
# standard python imports
import numpy as np
import matplotlib.pyplot as plt
import tidy3d as td
from tidy3d import web
from tidy3d.constants import C_0, HBAR
Gold dispersion with Drude model¶
In the visible frequency range, the dispersion of gold can be well approximated by the Drude model.
# Drude parameters for gold
eps_inf = 9.84 # relative permittivity at infinite frequency
wp = 9.01 #eV, plasma frequency
gamma = 0.072 #eV, damping rate
# Unit conversion from ev to Hz
wp_hz = wp / HBAR / 2 / np.pi
gamma_hz = gamma / HBAR / 2 / np.pi
# Tidy3d Drude model
mat_gold = td.Drude(eps_inf = eps_inf, coeffs = [(wp_hz,gamma_hz)], name='gold Drude')
Visualize the dispersion
# Compute permittivity in a range of wavelengths
lambda_list = np.linspace(0.3,0.6,500) # um
freq_list = C_0/lambda_list
ep = mat_gold.eps_model(freq_list)
# Visualize the real and imaginary part of permittivity
plt.rcParams.update({'font.size': 16})
fig, ax = plt.subplots(1,tight_layout=True,figsize=(5,4))
ax.plot(lambda_list,ep.real,label="Re[$\epsilon$]")
ax.plot(lambda_list,ep.imag,label="Im[$\epsilon$]")
ax.set_xlabel('Wavelength ($\mu$m)')
ax.set_xlim(lambda_list[0],lambda_list[-1])
ax.legend()
plt.show()
Other basic parameters¶
Now let us define the rest of basic parameters to setup the simulation. We consider placing a dipole source near the gold-air interface to excite the SPP.
# thickness of gold slab and air space
t_gold = 0.5 #um
t_air = 4 #um
# diple source position
distance = 0.02 #um, distance between the dipole source and the gold-air interface
px = 1 # um, distance between the dipole source and the left boundary of the simulation domain
# simulation size
Lx = 10 #um. we'll be looking at SPP propagating along x-direction, so let's make it long along x-axis
Ly = 2 #um
Lz = t_gold+t_air
sim_size = Lx, Ly, Lz
# Wavelength and frequency range of the source
lambda_range = (0.4,0.6)
lambda0 = (lambda_range[0] + lambda_range[1])/2
freq0 = C_0/lambda0
freqw = 0.3*(C_0/lambda_range[0]-C_0/lambda_range[1])
# runtime
runtime = 10
t_stop = runtime/freqw
# frequencies and wavelengths of field monitor
# we consider two representative wavelengths: 0.45 um for mirror-like response, and 0.55 um for SPP response
monitor_lambdas = np.array([0.45,0.55]) #um
monitor_freqs = C_0 / monitor_lambdas
Create Simulation¶
Now we set everything else up (structures, sources, monitors, simulation) to run the example.
# gold slab
gold_slab = td.Structure(
geometry=td.Box(
center=(0, 0, -Lz),
size=(td.inf,td.inf,Lz+2*t_gold),
),
medium=mat_gold,
name='gold slab',
)
# dipole source
source = td.PointDipole(
source_time = td.GaussianPulse(
freq0=freq0,
fwidth=freqw
),
center=(-Lx/2+px, 0, -Lz/2+t_gold+distance),
polarization='Ex',
name='dipole',
)
# field monitor
monitor = td.FieldMonitor(
center = (0, 0, 0),
size = (Lx, 0, Lz),
freqs = np.sort(monitor_freqs),
name='field',
)
# nonuniform mesh
grid_spec=td.GridSpec.auto(
min_steps_per_wvl=20,
)
sim = td.Simulation(
center = (0, 0, 0),
size = sim_size,
grid_spec = grid_spec,
structures = [gold_slab],
sources = [source],
monitors = [monitor],
run_time = t_stop,
boundary_spec = td.BoundarySpec.all_sides(boundary=td.PML()),
)
Plot The Structure¶
Let's now plot the permittivity profile to confirm that the structure was defined correctly. We use the Simulation.plot()
method to plot the materials only, which assigns a different color to each slab without knowledge of the material properties.
fig, ax = plt.subplots(1, tight_layout=True, figsize=(6, 4))
sim.plot(y=0, freq=freq0, ax=ax);
ax.set_title('')
ax.set_xlabel('x ($\mu$m)')
ax.set_ylabel('z ($\mu$m)')
plt.show()
Running simulation¶
We will submit the simulation to run as a new project.
sim_data = web.run(sim, task_name='lecture05_gold_SPP', path=f'data/data_gold_spp.hdf5')
Post Run Analysis¶
We visualize the field at the wavelength 450nm and 550 nm.
fig, ax = plt.subplots(1,2,figsize=(16, 4), tight_layout=True)
sim_data.plot_field('field', 'Ex', y=0, f=C_0/0.45, val='real', ax = ax[0], vmax = None)
ax[0].set_title('Wavelength: 450 nm')
ax[0].set_xlabel('x ($\mu$m)')
ax[0].set_ylabel('z ($\mu$m)')
sim_data.plot_field('field', 'Ex', y=0, f=C_0/0.55, val='real', ax = ax[1], vmax = None)
ax[1].set_title('Wavelength: 550 nm')
ax[1].set_xlabel('x ($\mu$m)')
ax[1].set_ylabel('z ($\mu$m)')
plt.show()