Simulation-to-Fabrication Workflow
Preview
This tutorial outlines the planned MetoSim → MetoFab pipeline. GDS export is available now; automated fabrication integration is coming with MetoFab.
Overview
The sim-to-fab workflow takes an optimized photonic design from MetoSim and prepares it for physical nanofabrication. The steps are:
- Simulate — Verify optical performance in MetoSim
- Export — Convert simulation geometry to GDS II
- Check — Run design rule checks against fab constraints
- Prepare — Generate process recipes and dose maps
- Fabricate — Send to foundry or in-house fab (MetoFab)
- Validate — Compare measured vs simulated response (MetoLab)
Step 1: Run the simulation
import metosim
client = metosim.MetoSimClient()
sim = metosim.Simulation(
solver="fdtd",
wavelength=1.55e-6,
geometry=[
metosim.Box(center=(0, 0, -0.5e-6), size=(10e-6, 4e-6, 1e-6), material="SiO2"),
metosim.Box(center=(0, 0, 0.11e-6), size=(10e-6, 0.5e-6, 0.22e-6), material="Si"),
],
domain_size=(12e-6, 4e-6, 4e-6),
resolution=20e-9,
time_steps=20000,
)
job = client.run(sim)
job.wait()
results = job.results(path="waveguide.hdf5")
Step 2: Verify simulation results
metosim.plot_field(results, component="Ez", slice_axis="z")
metosim.plot_structure(results, slice_axis="z")
# Check transmission
import h5py
import numpy as np
with h5py.File("waveguide.hdf5", "r") as f:
converged = f["metadata"].attrs["converged"]
print(f"Converged: {converged}")
warning
Never send an unconverged simulation to fabrication. Increase time_steps or check your PML configuration if the simulation didn't converge.
Step 3: Export to GDS (Available now)
Using gdstk to convert simulation geometry to GDS:
import gdstk
lib = gdstk.Library()
cell = gdstk.Cell("WAVEGUIDE")
# Si waveguide layer (Layer 1)
# Convert from simulation coordinates to GDS coordinates (μm)
waveguide = gdstk.rectangle(
(-5, -0.25), # corner 1 (x, y) in μm
(5, 0.25), # corner 2
layer=1,
datatype=0,
)
cell.add(waveguide)
lib.add(cell)
lib.write_gds("waveguide.gds")
print("GDS exported: waveguide.gds")
Step 4: Design rule check (manual, MetoFab will automate)
Before fabrication, verify:
# Check minimum feature sizes
waveguide_width_nm = 500 # nm
min_fab_feature_nm = 100 # EBL resolution
assert waveguide_width_nm >= min_fab_feature_nm, "Feature too small for EBL"
# Check minimum spacing (if multiple waveguides)
spacing_nm = 200
min_spacing_nm = 80
assert spacing_nm >= min_spacing_nm, "Gap too narrow"
print("✓ Design rules passed")
Step 5: Fabrication preparation
Typical SOI waveguide fabrication process:
Substrate: SOI wafer (220nm Si on 2μm SiO₂ on Si handle)
│
▼
Spin coat: ZEP-520A e-beam resist (~300nm)
│
▼
E-beam lithography: Write waveguide pattern
│ Dose: ~300 μC/cm² (adjust for proximity effects)
│ Beam: 100 kV, 1 nA
▼
Develop: o-xylene, 60s at 23°C
│
▼
Etch: ICP-RIE (SF₆/C₄F₈ Bosch-type or Cl₂/HBr)
│ Target: 220nm Si etch depth
│ Selectivity: >10:1 Si:SiO₂
▼
Strip resist: O₂ plasma ash
│
▼
Characterize: SEM + optical transmission measurement
Step 6: Compare sim vs measurement (MetoLab)
After fabrication and optical characterization:
import numpy as np
import matplotlib.pyplot as plt
# Simulated data (from MetoSim)
sim_wavelengths = np.linspace(1.5e-6, 1.6e-6, 100)
sim_transmission = np.ones_like(sim_wavelengths) * 0.92 # example
# Measured data (from MetoLab)
meas_wavelengths = np.linspace(1.5e-6, 1.6e-6, 50)
meas_transmission = np.ones_like(meas_wavelengths) * 0.87 + np.random.normal(0, 0.02, 50)
plt.figure(figsize=(10, 5))
plt.plot(sim_wavelengths * 1e9, sim_transmission, 'b-', label='Simulated (MetoSim)')
plt.plot(meas_wavelengths * 1e9, meas_transmission, 'ro', markersize=3, label='Measured (MetoLab)')
plt.xlabel("Wavelength (nm)")
plt.ylabel("Transmission")
plt.title("Simulation vs Measurement")
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig("sim_vs_measurement.png", dpi=150)
plt.show()
Next steps
- Inverse Design → — Optimize structures automatically
- MetoFab → — Automated fabrication pipeline (planned)