WDM Drop Filter @ 1550nm - Weekend Photonics Project
Center Wavelength
Quality Factor
Extinction Ratio
Free Spectral Range
Footprint
Silicon microring resonators offer a perfect introduction to integrated photonics: simple geometry yet rich physics, runs on free/academic software, and provides skills directly transferable to complex PIC designs. Master resonance, Q-factor, and coupling in a weekend!
Ultra-small footprint (<30µm × 30µm) with powerful wavelength selectivity. Ideal for dense photonic integration and WDM applications.
Explore resonance conditions, quality factors, coupling coefficients, and free spectral range through hands-on simulation.
Learn the complete PIC design flow: layout → mode solving → FDTD → compact modeling → circuit verification.
Choose your preferred tools - all options support the complete workflow
| Task | Open-Source / Free-Tier | Commercial (Trial/Edu) |
|---|---|---|
| Layout & Scripting | gdsfactory (Python) or KLayout + SiEPIC | Ansys Lumerical Layout |
| Eigen-mode Solver | mode_solver.py in Meep or MPB | Ansys MODE |
| 3D FDTD | Meep or Flexcompute Tidy3D (GPU cloud) | Ansys FDTD (2025 R1 trial) |
| Circuit Verification | Caphe in gdsfactory or simphony | Ansys INTERCONNECT |
All tools install with pip or run in the browser. gdsfactory even autogenerates Meep/Tidy3D scripts from your GDS layout. Check the awesome-photonics repo for alternative tools!
Create the ring resonator geometry using gdsfactory's parametric components.
💡 Keep waveguide width at 450nm for Si PIC foundry compatibility
Sweep waveguide width & slab height to extract effective refractive index (n_eff).
A quick 2D solver run tells you if the ring will be single-mode.
Automate parameter sweeps: radius (6-8 µm) & gap (0.12-0.25 µm). Measure S-parameters.
💡 Meep/Tidy3D jobs finish in minutes on a GPU instance
From the transmission spectrum, fit Lorentzian → Q, FSR, ER.
Convert fitted parameters to an INTERCONNECT or Caphe ring component.
Drop the device into a larger NRZ/PAM-4 link to see eye-diagrams.
With Tidy3D's autodiff API, optimize the bus-ring gap profile for max ER.
TidyGrad examples show 10-line scripts that converge in <50 iterations.
Explore the physics and design process through interactive tools
Complete Python workflow for ring resonator design and analysis
import gdsfactory as gf
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
# Step 1: Create parametric ring resonator
def create_ring_filter(radius=7, gap=0.15, width=0.45):
"""Create a single ring resonator drop filter"""
c = gf.Component()
# Create ring and bus waveguides
ring = c.add_ref(gf.components.ring(radius=radius, width=width))
bus = c.add_ref(gf.components.straight(length=2*radius+10))
# Position bus waveguide with specified gap
bus.movey(-radius - width/2 - gap - width/2)
# Add ports
c.add_port("in", port=bus.ports["o1"])
c.add_port("through", port=bus.ports["o2"])
c.add_port("drop", port=ring.ports["o2"])
c.add_port("add", port=ring.ports["o1"])
return c
# Step 2: FDTD simulation setup (using Tidy3D)
def simulate_ring(component, wavelengths):
"""Run FDTD simulation and extract S-parameters"""
import tidy3d as td
# Convert GDS to simulation geometry
sim = gf.plugins.tidy3d.get_simulation(
component=component,
wavelength=1.55,
wavelength_span=0.1,
port_source="in",
port_monitors=["through", "drop"],
mesh_accuracy=3
)
# Run simulation
data = td.web.run(sim, task_name="ring_resonator")
# Extract S-parameters
S21 = data["through"].amps
S31 = data["drop"].amps
return S21, S31
# Step 3: Analyze resonances
def lorentzian(x, x0, gamma, A, offset):
"""Lorentzian function for resonance fitting"""
return A * gamma**2 / ((x - x0)**2 + gamma**2) + offset
def extract_metrics(wavelengths, transmission):
"""Extract Q-factor, FSR, and extinction ratio"""
# Find resonances
from scipy.signal import find_peaks
peaks, _ = find_peaks(-transmission, height=0.1)
# Fit Lorentzian to each resonance
metrics = []
for peak in peaks:
# Select data around peak
idx_range = slice(max(0, peak-20), min(len(wavelengths), peak+20))
x_fit = wavelengths[idx_range]
y_fit = transmission[idx_range]
# Initial guess
x0_guess = wavelengths[peak]
gamma_guess = 0.0004 # ~0.8nm FWHM
A_guess = 1 - np.min(y_fit)
offset_guess = np.max(y_fit)
# Fit
popt, _ = curve_fit(lorentzian, x_fit, y_fit,
p0=[x0_guess, gamma_guess, A_guess, offset_guess])
# Calculate metrics
resonance_wavelength = popt[0]
fwhm = 2 * popt[1]
Q_factor = resonance_wavelength / fwhm
extinction_ratio_dB = -10 * np.log10(np.min(y_fit) / np.max(y_fit))
metrics.append({
'wavelength': resonance_wavelength,
'Q': Q_factor,
'ER_dB': extinction_ratio_dB,
'FWHM_nm': fwhm * 1000 # Convert to nm
})
# Calculate FSR
if len(metrics) > 1:
fsr_nm = np.diff([m['wavelength'] for m in metrics]).mean() * 1000
fsr_ghz = 3e8 / (1.55e-6)**2 * fsr_nm * 1e-9 * 1e9 # Convert to GHz
else:
fsr_nm = fsr_ghz = None
return metrics, fsr_ghz
# Step 4: Parameter sweep
def sweep_design_space():
"""Sweep radius and gap to optimize performance"""
radii = np.linspace(6, 8, 5)
gaps = np.linspace(0.12, 0.25, 5)
results = []
for radius in radii:
for gap in gaps:
# Create design
ring = create_ring_filter(radius=radius, gap=gap)
# Simulate (simplified - would use actual FDTD)
# Here we use analytical approximation
Q_loaded = estimate_Q(radius, gap)
ER = estimate_ER(gap)
results.append({
'radius': radius,
'gap': gap,
'Q': Q_loaded,
'ER_dB': ER
})
return results
# Helper functions for analytical estimates
def estimate_Q(radius, gap):
"""Estimate loaded Q-factor"""
# Coupling coefficient (empirical model)
kappa = np.exp(-2 * gap / 0.1) # Simplified exponential model
# Intrinsic Q (loss-limited)
Q_intrinsic = 50000 # Typical for low-loss SOI
# Loaded Q
Q_loaded = Q_intrinsic / (1 + kappa * Q_intrinsic)
return Q_loaded
def estimate_ER(gap):
"""Estimate extinction ratio"""
kappa = np.exp(-2 * gap / 0.1)
ER_linear = (1 - kappa)**2 / (4 * kappa)
return 10 * np.log10(ER_linear)
# Step 5: Generate compact model
def create_compact_model(ring_params, s_params):
"""Generate Caphe/INTERCONNECT compatible model"""
model = {
'type': 'ring_resonator',
'parameters': ring_params,
'ports': ['in', 'through', 'drop', 'add'],
's_parameters': s_params,
'center_wavelength': 1.55e-6,
'ng': 4.2, # Group index
'loss_dB_per_cm': 2.0
}
return model
# Main execution
if __name__ == "__main__":
# Create optimized design
ring = create_ring_filter(radius=7.2, gap=0.18)
# Export GDS
ring.write_gds("ring_filter.gds")
# Run parameter sweep
results = sweep_design_space()
# Find optimal design
optimal = max(results, key=lambda x: x['ER_dB'] if x['Q'] > 1500 else 0)
print(f"Optimal Design:")
print(f" Radius: {optimal['radius']:.1f} µm")
print(f" Gap: {optimal['gap']:.3f} µm")
print(f" Q-factor: {optimal['Q']:.0f}")
print(f" Extinction Ratio: {optimal['ER_dB']:.1f} dB")
Take your design further with these advanced features
Add a heater layer in layout & simulate Δn(T). Demonstrates active control using coupled-mode theory. Essential for practical WDM systems.
Cascade rings of different radii for >40 dB rejection. Perfect for dense WDM applications requiring ultra-narrow filtering.
Use the ring as a feedback sensor in a control loop. Combines photonics with control theory - impressive for technical interviews!
Complete Python script that generates GDS, runs parameter sweeps, and plots S-parameters. Fully documented with markdown explanations.
Annotated figures showing Q-factor, extinction ratio, and FSR. Include both simulation results and fitted analytical models.
One-page PDF summarizing specifications, field snapshots, and fit results. Professional format suitable for portfolio or technical review.
(Extra Credit) PIC-level eye-diagram comparing NRZ link performance with and without the filter block.
Browser-based applets for ring resonators and MZIs. Great for building intuition before diving into code.
Explore Virtual Lab →Traveling-wave MZM tutorial shows end-to-end multi-physics setup. Same workflow applies to ring resonators.
View Tutorial →ResearchGate thread links several open PDKs compatible with Meep/gdsfactory. Simulate realistic foundry layers!
Browse Resources →Setup tools, create initial layout, run mode solver checks
FDTD parameter sweeps, optimize gap & radius
Extract metrics, build compact model, validate
Circuit-level verification, eye diagram analysis
Documentation, create report, optional extensions