Skip to content

Ring coupler with GDSFactory FDTD

Run a 3D simulation using gsim.fdtd, a 60 nm Yee grid, and the active PDK. Exciting o1 returns one column of the S-matrix.

Requirements: gsim>=0.8.0 and GDSFactory+ cloud simulation access. To update an older project environment, run uv add "gsim>=0.8.0" "pdk-schema[sympy]~=0.3.0" from your project folder, then restart the notebook kernel.

Load a component from the active PDK

import gdsfactoryplus as gfp

pdk = gfp.get_pdk()
pdk.activate()
import gdsfactory as gf

component = gf.get_component("coupler_ring", length_x=10)
component = component.copy()
component.auto_rename_ports()
component

png

Configure the 3D simulation

Use the PDK layer stack with lossless silicon (n = 3.47) and silica (n = 1.44) at 1.55 µm. Sweep 1.50–1.60 µm; weak source-spectrum tails are hidden in the plots.

The curved-arm ports lie on the upper Y boundary. Add cladding below the bus with padding_y=(1.0, 0.0) so its sloped sidewalls fit inside the physical domain while the upper ports remain on the boundary.

from gsim import fdtd

sim = fdtd.Simulation(pdk=pdk)
sim.materials(background="SiO2", overrides={"si": 3.47, "SiO2": 1.44})
sim.geometry(component=component, geometry_tolerance_nm=10)
sim.source(
    port="o1",
    wavelength_um=1.55,
    wavelength_span_um=0.1,
    num_wavelengths=101,
)
sim.domain(padding=1.0, padding_y=(1.0, 0.0), pml_cells=20)
sim.solver(cell_size_nm=60, energy_decay_fraction=1e-6, max_wall_seconds=3600)
Solver(cell_size_nm=60.0, max_timesteps=None, energy_decay_fraction=1e-06, max_wall_seconds=3600.0)

Inspect the geometry and record the field

The interactive 3D view shows the device geometry and ports. An XY monitor through the input waveguide core records field intensity at the center wavelength, separately from the guided-port S-parameter monitors.

core_z_um = sim.resolved.ports[sim.source.port].center[2]
sim.monitors.add_plane(
    name="overview_xy",
    center_um=(component.dx, component.dy, core_z_um),
    size_um=(component.dxsize, component.dysize, 0),
    normal="+z",
    flux=False,
    heatmap=fdtd.Heatmap(quantity="intensity", wavelengths_um=[1.55]),
)

sim.plot_3d()

Run on the cloud

Reuse a completed run when the simulation inputs match.

result = sim.run(check_cache=True)
  fdtd-3a9942a6  [####################] 100%  complete  elapsed 0m 00s


Extracting results.tar.gz...
Downloaded 3 files to /home/runner/work/simulation-templates/simulation-templates/docs/notebooks/sim-data-fdtd-3a9942a6

Inspect the S-parameters

Inspect the split between the bus and curved coupling arm. This is an open four-port coupler, not a closed ring resonator.

result.s_parameters.plot_plotly()
result.s_parameters.plot_plotly(quantity="phase_deg")

Field intensity

Use equal X and Y scales so a micrometer has the same displayed length in each direction.

field_figure, field_axis = result.monitors["overview_xy"].plot_heatmap(
    wavelength_um=sim.source.wavelength_um
)
field_axis.set_aspect("equal", adjustable="box")

png