Palace Directional Coupler Simulation - Wave Ports¶
This notebook mirrors the geometry in meep_dc.ipynb, but configures a Palace driven simulation with waveport boundary conditions.
MEEP-specific features (for example FDTD PML/animation details) are omitted.
Load the same directional coupler geometry¶
from pathlib import Path
import gdsfactory.component as gfc
from ubcpdk import PDK, cells
# Use a workspace-local temp path for layer preview artifacts.
gds_tmp = Path.cwd() / ".gdsfactory_tmp"
gds_tmp.mkdir(parents=True, exist_ok=True)
gfc.GDSDIR_TEMP = gds_tmp
PDK.activate()
c = cells.coupler()
cc = c.copy()
cc.draw_ports()
cc
Configure Palace driven simulation with waveports¶
from gsim.palace import DrivenSim
sim = DrivenSim()
sim.set_output_dir("./palace-sim-dc-waveport")
sim.set_geometry(c)
sim.set_stack(
substrate_thickness=2.0,
add_oxide_dielectric=False,
add_passivation_dielectric=False,
)
# Use direct sparse solve backend.
sim.set_numerical(
solver_type="MUMPS",
max_iterations=1,
tolerance=1e-8,
)
for i, port in enumerate(c.ports):
sim.add_wave_port(
str(port.name),
layer="core",
z_margin=1.5,
lateral_margin=1.5,
max_size=False,
mode=1,
excited=(i == 0),
)
# Around 1.55 um (~193.5 THz).
sim.set_driven(fmin=190e12, fmax=200e12, num_points=21)
print(sim.validate_config())
import gdsfactory as gf
active = gf.get_active_pdk()
print("Active PDK:", active.name)
stack = sim._resolve_stack()
print("Stack layers:")
for name, layer in stack.layers.items():
print(
f" - {name}: type={layer.layer_type}, material={layer.material}, "
f"gds={tuple(layer.gds_layer)}, z=({layer.zmin}, {layer.zmax})"
)
print("\nMaterial properties (selected):")
for key in ("si", "sio2", "SiO2", "air"):
if key in stack.materials:
print(f" - {key}: {stack.materials[key]}")
print("\nDielectric regions:")
for d in stack.dielectrics:
print(f" - {d}")
Generate mesh¶
sim.set_airbox(
margin_x=0.0,
margin_y=1.5,
z_above=0.5,
z_below=0.5,
)
# fmax=220 THz -> lambda0~1.36 um. In Si (n~3.45), lambda~0.395 um,
# so for >=5 points per wavelength use mesh size <=0.079 um.
sim.mesh(
preset="fine",
refined_mesh_size=0.05,
max_mesh_size=0.25,
fmax=220e12,
curve_fit_mode="bspline",
curve_fit_layers=["core", "core2"],
curve_fit_tolerance_um=0.01,
curve_fit_min_points=8,
high_order_elements=True,
high_order_order=2,
high_order_optimize=True,
)
Run simulation¶
for p in sim._last_mesh_result.port_info:
print(
f"{p['type']} P{p['portnumber']}: "
f"z=({p['zmin']:.3f}, {p['zmax']:.3f}), "
f"x=({p['xmin']:.3f}, {p['xmax']:.3f}), "
f"y=({p['ymin']:.3f}, {p['ymax']:.3f})"
)