2D Grating Coupler: Wavelength Sweep¶
A parallel sweep of the design wavelength for the 2D XZ grating-coupler
workflow (see meep_2d_xz_gc.ipynb for the single-shot version).
We sweep over 1.54, 1.55, 1.56 µm. At each wavelength both the coupler
geometry (grating_coupler_elliptical(wavelength=...) re-tunes the grating
pitch/teeth) and the Gaussian-beam source are set to that wavelength. All
simulations run on the GDSFactory+ cloud via the non-blocking API, then we
overlay the coupling S-parameter for every wavelength in a single plot.
Requirements: GDSFactory+ account for cloud simulation.
Define the sweep¶
Build a grating coupler + feed straight for a given wavelength¶
import gdsfactory as gf
gf.gpdk.PDK.activate()
def make_component(wavelength: float) -> gf.Component:
"""Grating coupler tuned to ``wavelength`` plus a 3 µm feed straight."""
c = gf.Component()
gc = gf.components.grating_coupler_elliptical(
wavelength=wavelength, fiber_angle=0.0
)
gc_r = c.add_ref(gc)
s_r = c.add_ref(gf.components.straight(length=3))
s_r.connect("o1", gc_r.ports["o1"])
c.add_port("o2", port=s_r.ports["o2"])
return c
make_component(wavelengths_um[len(wavelengths_um) // 2]) # preview mid-sweep design

Configure one XZ 2D simulation per wavelength¶
Same XZ setup as meep_2d_xz_gc.ipynb, but the coupler geometry and the
source_fiber(wavelength=...) are both varied per point. save_animation=False
keeps the sweep light since we only need S-params.
from gsim import meep
from gsim.common.stack import get_stack
from gsim.meep.models.api import Material
stack = get_stack() # auto-detects active PDK
sims = []
for wl in wavelengths_um:
c = make_component(wl)
sim = meep.Simulation()
sim.geometry(component=c, stack=stack)
sim.materials = {
"si": Material(refractive_index=3.47),
"SiO2": Material(refractive_index=1.44),
}
sim.solver(resolution=25, mode="2d", y_cut="auto", save_animation=False)
sim.solver.stop_when_energy_decayed()
sim.source_fiber(
x=25.0,
z=2,
angle_deg=-6.0,
waist=5.2,
wavelength=wl,
wavelength_span=0.06,
polarization="TE",
)
sim.monitors = ["o2"]
sim.domain(pml=1.0, margin_x=0.5, margin_y=0.5, margin_z=(1.5, 0))
sim.num_freqs = 21
sims.append(sim)
print(f"Configured {len(sims)} simulations for wavelengths {wavelengths_um}")
pyvirtualdisplay not available; continuing without Xvfb
Configured 3 simulations for wavelengths [1.54, 1.55, 1.56]
Upload and start all jobs (non-blocking)¶
job_ids = [sim.run(wait=False, check_cache=True) for sim in sims]
print(f"Started {len(job_ids)} jobs: {job_ids}")
simulation.py:1625: FutureWarning: Use of domain.margin_z is deprecated and will be removed in a future release; replace it with domain.z_bounds=(-1.5, 4.6).
result = self.build_config()
Cache hit: reusing job 01a01a1f-a3c6-7c11-8b4d-1d481573fda2
Cache hit: reusing job 01a01a1f-a95c-7693-8032-639b439504ea
Cache hit: reusing job 01a01a1f-af9e-7862-a1a1-293f530beba5
Started 3 jobs: ['01a01a1f-a3c6-7c11-8b4d-1d481573fda2', '01a01a1f-a95c-7693-8032-639b439504ea', '01a01a1f-af9e-7862-a1a1-293f530beba5']
Wait for all jobs to complete¶
Waiting for 3 jobs...
meep-761ac8dc completed 0m 00s
meep-5462e6a6 completed 0m 00s
meep-c6417d94 completed 0m 00s
Extracting results.tar.gz...
Downloaded 4 files to sim-data-meep-761ac8dc
Extracting results.tar.gz...
Downloaded 4 files to sim-data-meep-5462e6a6
Extracting results.tar.gz...
Downloaded 4 files to sim-data-meep-c6417d94
Overlay coupling S-parameter vs wavelength¶
The fiber source produces a single transmission S-parameter (S10) from the
beam into the feed waveguide o2. We overlay it in dB for every design
wavelength; each sim covers a small band around its center.
import math
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(7, 4))
for wl, sp in zip(wavelengths_um, results, strict=True):
key = next(iter(sp.s_params)) # single transmission param, e.g. "S10"
db = [20 * math.log10(abs(v)) if abs(v) > 0 else -100 for v in sp.s_params[key]]
ax.plot(sp.wavelengths, db, ".-", label=f"{wl:.2f} µm")
ax.set(
xlabel="Wavelength (µm)",
ylabel="Coupling |S| (dB)",
title="Grating-coupler coupling vs design wavelength",
)
ax.legend(title="Design wavelength")
ax.grid(True, alpha=0.3)
fig.tight_layout()
