Sweep the microstrip width from 5 to 50 um (5 points), run all simulations in parallel on GDSFactory+ cloud using the non-blocking API, then compare S11 and S21 across widths.
Requirements:
- IHP PDK:
uv pip install ihp-gdsfactory - GDSFactory+ account for cloud simulation
Define the sweep¶
Build components and configure simulations¶
import gdsfactory as gf
from ihp import LAYER, PDK, cells
from gsim.palace import DrivenSim
PDK.activate()
sims = []
for w in widths:
# Build component
c = gf.Component()
r1 = c << cells.straight_metal(length=1000, width=w)
r = c.get_region(layer=LAYER.TopMetal2drawing)
r_sized = r.sized(+20000)
c.add_polygon(r_sized, layer=LAYER.Metal1drawing)
c.add_ports(r1.ports)
# Configure simulation
sim = DrivenSim()
sim.set_output_dir(f"./palace-sim-w{w:.1f}")
sim.set_geometry(c)
sim.set_stack(substrate_thickness=2.0, air_above=300.0)
for port in c.ports:
sim.add_port(
port.name, from_layer="metal1", to_layer="topmetal2", geometry="via"
)
sim.set_driven(fmin=1e9, fmax=100e9, num_points=80)
sim.mesh(preset="default")
sims.append(sim)
print(f"Configured {len(sims)} simulations")
Warning : 6 ill-shaped tets are still in the mesh
Warning : 1 ill-shaped tets are still in the mesh
Warning : ------------------------------
Warning : Mesh generation error summary
Warning : 2 warnings
Warning : 0 errors
Warning : Check the full log for details
Warning : ------------------------------
Warning : 5 ill-shaped tets are still in the mesh
Warning : ------------------------------
Warning : Mesh generation error summary
Warning : 1 warning
Warning : 0 errors
Warning : Check the full log for details
Warning : ------------------------------
Warning : 8 ill-shaped tets are still in the mesh
Warning : ------------------------------
Warning : Mesh generation error summary
Warning : 1 warning
Warning : 0 errors
Warning : Check the full log for details
Warning : ------------------------------
Warning : 7 ill-shaped tets are still in the mesh
Warning : ------------------------------
Warning : Mesh generation error summary
Warning : 1 warning
Warning : 0 errors
Warning : Check the full log for details
Warning : ------------------------------
Warning : 15 ill-shaped tets are still in the mesh
Configured 5 simulations
Warning : ------------------------------
Warning : Mesh generation error summary
Warning : 1 warning
Warning : 0 errors
Warning : Check the full log for details
Warning : ------------------------------
Upload and start all jobs (non-blocking)¶
# Upload and start all jobs without waiting
job_ids = []
for sim in sims:
job_id = sim.run(wait=False)
job_ids.append(job_id)
print(f"Started {len(job_ids)} jobs: {job_ids}")
Job started: palace-97e4b582
Job started: palace-58781c83
Job started: palace-75903c18
Job started: palace-a5f9ab59
Job started: palace-4c1fc999
Started 5 jobs: ['019d3301-1abf-73a2-8979-a2973042142a', '019d3301-20ae-75d2-bdca-ac14f72d95c9', '019d3301-2668-7d80-87ae-aaa9b79d6f2e', '019d3301-2c3b-7920-83b5-c17e2bd112d3', '019d3301-31cb-7210-95c1-15ab7be17e89']
Wait for all jobs to complete¶
import gsim
# Poll all jobs concurrently, download and parse results
results = gsim.wait_for_results(job_ids)
Waiting for 5 jobs...
palace-97e4b582 completed 5m 11s
palace-58781c83 completed 5m 23s
palace-75903c18 completed 7m 04s
palace-a5f9ab59 completed 4m 53s
palace-4c1fc999 completed 6m 38s
Extracting results.tar.gz...
Downloaded 10 files to /home/runner/work/gsim/gsim/nbs/sim-data-palace-97e4b582
Extracting results.tar.gz...
Downloaded 10 files to /home/runner/work/gsim/gsim/nbs/sim-data-palace-58781c83
Extracting results.tar.gz...
Downloaded 10 files to /home/runner/work/gsim/gsim/nbs/sim-data-palace-75903c18
Extracting results.tar.gz...
Downloaded 10 files to /home/runner/work/gsim/gsim/nbs/sim-data-palace-a5f9ab59
Extracting results.tar.gz...
Downloaded 10 files to /home/runner/work/gsim/gsim/nbs/sim-data-palace-4c1fc999
Plot S11 and S21 comparison¶
import matplotlib.pyplot as plt
from gsim.palace import load_sparams
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(6, 6))
for w, result_files in zip(widths, results):
sp = load_sparams(result_files)
ax1.plot(sp.freq, sp.s11.db, label=f"w={w:.1f} um")
ax2.plot(sp.freq, sp.s21.db, label=f"w={w:.1f} um")
ax1.set(
xlabel="Frequency (GHz)", ylabel="|S11| (dB)", title="S11 — Return Loss vs Width"
)
ax1.legend()
ax1.grid(True)
ax2.set(
xlabel="Frequency (GHz)", ylabel="|S21| (dB)", title="S21 — Insertion Loss vs Width"
)
ax2.legend()
ax2.grid(True)
plt.tight_layout()
