Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 34 additions & 13 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,36 @@ on:
- main
tags:
- "[0-9]+.[0-9]+.[0-9]+"
pull_request:
workflow_dispatch:

env:
GFP_API_KEY: ${{ secrets.GFP_API_KEY }}

jobs:
run-notebooks:
# Discover all notebooks and output as JSON array for the matrix
list-notebooks:
runs-on: ubuntu-latest
outputs:
notebooks: ${{ steps.find.outputs.notebooks }}
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
- name: Find notebooks
id: find
run: |
nbs=$(find nbs -name "*.ipynb" -not -path "*/.ipynb_checkpoints/*" | sort | jq -Rsc 'split("\n") | map(select(. != ""))')
echo "notebooks=$nbs" >> "$GITHUB_OUTPUT"

# Run each notebook in parallel
run-notebook:
runs-on: ubuntu-latest
needs: list-notebooks
strategy:
matrix:
notebook: ${{ fromJson(needs.list-notebooks.outputs.notebooks) }}
fail-fast: false
steps:
- name: Checkout repo
uses: actions/checkout@v4
Expand All @@ -29,24 +51,22 @@ jobs:
run: just dev
- name: Create ipykernel
run: uv run --no-sync python -m ipykernel install --user --name gsim
- name: Run notebooks
- name: Run notebook
run: |
for nb in $(find nbs -name "*.ipynb" -not -path "*/.ipynb_checkpoints/*" | sort); do
dir=$(dirname "$nb")
filename=$(basename "$nb")
(cd "$dir" && xvfb-run -a uv run --no-sync papermill "$filename" "$filename" -k gsim)
done
- name: Upload executed notebooks
dir=$(dirname "${{ matrix.notebook }}")
filename=$(basename "${{ matrix.notebook }}")
cd "$dir" && xvfb-run -a uv run --no-sync papermill "$filename" "$filename" -k gsim
- name: Upload executed notebook
uses: actions/upload-artifact@v4
with:
name: nbs
path: nbs
name: nb-${{ hashFiles(matrix.notebook) }}
path: ${{ matrix.notebook }}
retention-days: 1

build:
name: Build Docs
runs-on: ubuntu-latest
needs: run-notebooks
needs: run-notebook
steps:
- name: Checkout repo
uses: actions/checkout@v4
Expand All @@ -68,7 +88,8 @@ jobs:
- name: Download all notebook artifacts
uses: actions/download-artifact@v4
with:
name: nbs
pattern: nb-*
merge-multiple: true
path: nbs
- name: Build docs
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
tags:
- "[0-9]*.[0-9]*.[0-9]*"
pull_request:
workflow_dispatch:

jobs:
build:
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ nav:
- examples:
- Simple Example: nbs/example.md
- MEEP Y-Branch: nbs/meep_ybranch.md
- MEEP Ring Coupler: nbs/meep_ring_coupler.md
- Palace CPW: nbs/palace_demo_cpw.md
- Palace Microstrip: nbs/palace_demo_microstrip.md
- api reference:
Expand Down
102 changes: 102 additions & 0 deletions nbs/meep_api_styles.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# MEEP API Styles\n",
"\n",
"The `gsim.meep` API supports three equivalent styles for configuring simulations.\n",
"All three produce identical `Simulation` objects — pick whichever reads best for your use case."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from ubcpdk import PDK, cells\n",
"\n",
"PDK.activate()\n",
"c = cells.ebeam_y_1550()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Callable style (recommended)\n",
"\n",
"Updates fields in place — only the fields you pass change, others keep their current values. No extra imports needed."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": "from gsim import meep\n\nsim = meep.Simulation()\n\nsim.geometry(component=c, z_crop=\"auto\")\nsim.materials = {\"si\": 3.47, \"SiO2\": 1.44}\nsim.source(port=\"o1\", wavelength=1.55, wavelength_span=0.01, num_freqs=11)\nsim.monitors = [\"o1\", \"o2\", \"o3\"]\nsim.domain(pml=1.0, margin=0.5)\nsim.solver(resolution=20, simplify_tol=0.01, save_animation=True, verbose_interval=5.0)"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Attribute style\n",
"\n",
"One field per line. Most explicit — good when you need to set fields conditionally."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": "from gsim import meep\n\nsim = meep.Simulation()\n\nsim.geometry.component = c\nsim.geometry.z_crop = \"auto\"\n\nsim.materials = {\"si\": 3.47, \"SiO2\": 1.44}\n\nsim.source.port = \"o1\"\nsim.source.wavelength = 1.55\nsim.source.wavelength_span = 0.01\nsim.source.num_freqs = 11\n\nsim.monitors = [\"o1\", \"o2\", \"o3\"]\n\nsim.domain.pml = 1.0\nsim.domain.margin = 0.5\n\nsim.solver.resolution = 20\nsim.solver.simplify_tol = 0.01\nsim.solver.save_animation = True\nsim.solver.verbose_interval = 5.0"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Constructor style\n",
"\n",
"Replaces the entire sub-object — fields you don't pass reset to defaults. Requires importing model classes, but useful when building configs programmatically or from saved presets."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": "from gsim import meep\nfrom gsim.meep import Domain, FDTD, Geometry, ModeSource\n\nsim = meep.Simulation()\n\nsim.geometry = Geometry(component=c, z_crop=\"auto\")\nsim.materials = {\"si\": 3.47, \"SiO2\": 1.44}\nsim.source = ModeSource(port=\"o1\", wavelength=1.55, wavelength_span=0.01, num_freqs=11)\nsim.monitors = [\"o1\", \"o2\", \"o3\"]\nsim.domain = Domain(pml=1.0, margin=0.5)\nsim.solver = FDTD(\n resolution=20, simplify_tol=0.01, save_animation=True, verbose_interval=5.0\n)"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Combining styles\n",
"\n",
"All three styles can be freely combined. For example, use callable for bulk setup, then attribute for conditional tweaks:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": "from gsim import meep\n\nsim = meep.Simulation()\n\nsim.geometry(component=c, z_crop=\"auto\")\nsim.materials = {\"si\": 3.47, \"SiO2\": 1.44}\nsim.source(port=\"o1\", wavelength=1.55, wavelength_span=0.01, num_freqs=11)\nsim.monitors = [\"o1\", \"o2\", \"o3\"]\nsim.domain(pml=1.0, margin=0.5)\nsim.solver(resolution=20, simplify_tol=0.01)\n\n# Conditional tweaks with attribute style\ndebug = True\nif debug:\n sim.solver.save_animation = True\n sim.solver.verbose_interval = 5.0"
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
142 changes: 142 additions & 0 deletions nbs/meep_ring_coupler.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "0",
"metadata": {},
"source": [
"# Running MEEP Simulations\n",
"\n",
"[MEEP](https://meep.readthedocs.io/) is an open-source FDTD electromagnetic simulator. This notebook demonstrates using the `gsim.meep` API to run an S-parameter simulation on a photonic Y-branch.\n",
"\n",
"**Requirements:**\n",
"\n",
"- UBC PDK: `uv pip install ubcpdk`\n",
"- [GDSFactory+](https://gdsfactory.com) account for cloud simulation"
]
},
{
"cell_type": "markdown",
"id": "1",
"metadata": {},
"source": [
"### Load a pcell from UBC PDK"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2",
"metadata": {},
"outputs": [],
"source": [
"from ubcpdk import PDK, cells\n",
"\n",
"PDK.activate()\n",
"\n",
"c = cells.coupler_ring(gap=0.15)\n",
"\n",
"c"
]
},
{
"cell_type": "markdown",
"id": "3",
"metadata": {},
"source": [
"### Configure and run simulation"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4",
"metadata": {},
"outputs": [],
"source": [
"from gsim import meep\n",
"\n",
"sim = meep.Simulation()\n",
"\n",
"sim.geometry(component=c, z_crop=\"auto\")\n",
"sim.materials = {\"si\": 3.47, \"SiO2\": 1.44}\n",
"sim.source(port=\"o1\", wavelength=1.55, wavelength_span=0.01, num_freqs=11)\n",
"sim.monitors = [\"o1\", \"o2\", \"o3\", \"o4\"]\n",
"sim.domain(pml=1.0, margin=0.5)\n",
"sim.solver(resolution=20, save_animation=True, verbose_interval=5.0)\n",
"sim.solver.stop_after_sources(time=100)\n",
"\n",
"print(sim.validate_config())"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5",
"metadata": {},
"outputs": [],
"source": [
"sim.plot_2d(slices=\"xyz\")"
]
},
{
"cell_type": "markdown",
"id": "6",
"metadata": {},
"source": [
"### Run simulation on cloud"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7",
"metadata": {},
"outputs": [],
"source": [
"# Run on GDSFactory+ cloud\n",
"result = sim.run()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8",
"metadata": {},
"outputs": [],
"source": [
"result.plot(db=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9",
"metadata": {},
"outputs": [],
"source": [
"result.show_animation()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "gsim",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading