File size: 6,357 Bytes
fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 b53e7e7 fa34304 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import tempfile
import gradio as gr
from bpm.refractive_index import (
generate_waveguide_n_r2,
generate_MMI_n_r2
)
from bpm.mode_solver import slab_mode_source
from bpm.core import run_bpm
from bpm.pml import generate_sigma_x
def run_waveguide(w, l, L_bend, n_WG, wavelength, ind_m):
# --- Simulation setup (Waveguide S-bend) ---
domain_size = 50.0
z_total = 500.0
Nx, Nz = 256, 2000
x = np.linspace(-domain_size/2, domain_size/2, Nx)
z = np.linspace(0, z_total, Nz)
n0 = 1.0
# Refractive index map
n_r2 = generate_waveguide_n_r2(x, z, l, L_bend, w, n_WG, n0)
# Launch slab mode
E0 = slab_mode_source(x, w, n_WG, n0, wavelength, ind_m, x0=0)
E = np.zeros((Nx, Nz), dtype=np.complex128)
E[:, 0] = E0
# PML + BPM
dx = domain_size / Nx
dz = z[1] - z[0]
sigma_x = generate_sigma_x(x, dx, wavelength, domain_size)
E_out = run_bpm(E, n_r2, x, z, dx, dz, n0, sigma_x, wavelength)
# Plot
fig, ax = plt.subplots(figsize=(8,6))
im = ax.imshow(
np.abs(E_out)**2,
extent=[x[0], x[-1], z[0], z[-1]],
origin='lower',
aspect='auto',
cmap='inferno'
)
ax.set_title("Waveguide S-bend BPM Propagation")
ax.set_xlabel("x (µm)")
ax.set_ylabel("z (µm)")
fig.colorbar(im, ax=ax, label="Intensity")
# Save data for download
tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".npz")
np.savez(tmp.name, E_out=E_out, x=x, z=z)
tmp.close()
return fig, tmp.name
def run_mmi(z_start, L_MMI, w_MMI, w_wg, d, n_WG, wavelength, ind_m):
# --- Simulation setup (MMI Splitter) ---
domain_size = 50.0
z_total = 250.0
Nx, Nz = 256, 1024
x = np.linspace(-domain_size/2, domain_size/2, Nx)
z = np.linspace(0, z_total, Nz)
n0 = 1.0
# For simplicity, use the same core and MMI index
n_MMI = n_WG
# Refractive index map
n_r2 = generate_MMI_n_r2(
x, z,
z_MMI_start = z_start,
L_MMI = L_MMI,
w_MMI = w_MMI,
w_wg = w_wg,
d = d,
n_WG = n_WG,
n_MMI = n_MMI,
n0 = n0
)
# Launch slab mode in left waveguide
E0 = slab_mode_source(x, w_wg, n_WG, n0, wavelength, ind_m, x0=-d/2)
E = np.zeros((Nx, Nz), dtype=np.complex128)
E[:,0] = E0
# PML + BPM
dx = domain_size / Nx
dz = z[1] - z[0]
sigma_x = generate_sigma_x(x, dx, wavelength, domain_size)
E_out = run_bpm(E, n_r2, x, z, dx, dz, n0, sigma_x, wavelength)
# Plot
fig, ax = plt.subplots(figsize=(8,6))
im = ax.imshow(
np.abs(E_out)**2,
extent=[x[0], x[-1], z[0], z[-1]],
origin='lower',
aspect='auto',
cmap='inferno'
)
ax.set_title("MMI Splitter BPM Propagation")
ax.set_xlabel("x (µm)")
ax.set_ylabel("z (µm)")
fig.colorbar(im, ax=ax, label="Intensity")
# Save data
tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".npz")
np.savez(tmp.name, E_out=E_out, x=x, z=z)
tmp.close()
return fig, tmp.name
def run_dispatcher(
sim_type,
# waveguide args
w, l, L_bend,
# mmi args
z_start, L_MMI, w_MMI, w_wg, d,
# common args
n_WG, wavelength, ind_m
):
if sim_type == "Waveguide S-bend":
return run_waveguide(w, l, L_bend, n_WG, wavelength, ind_m)
else:
return run_mmi(z_start, L_MMI, w_MMI, w_wg, d, n_WG, wavelength, ind_m)
with gr.Blocks() as demo:
gr.Markdown("## BPM Simulation Dashboard")
# 1) Simulation selector
sim_type = gr.Radio(
choices=["Waveguide S-bend", "MMI Splitter"],
value="Waveguide S-bend",
label="Simulation Type"
)
with gr.Row():
# 2) Waveguide parameters panel
with gr.Column(visible=True) as waveguide_panel:
w_slider = gr.Slider(0.1, 5.0, value=1.0, step=0.1, label="Waveguide width w (µm)")
l_slider = gr.Slider(0.0, 10.0, value=5.0, step=0.1, label="Lateral offset l (µm)")
Lb_slider = gr.Slider(50.0, 500.0,value=200.0,step=10.0,label="S-bend length L (µm)")
# 3) MMI parameters panel
with gr.Column(visible=False) as mmi_panel:
z0_slider = gr.Slider(0.0, 200.0, value=50.0, step=1.0, label="MMI start z₀ (µm)")
Lmmi_slider = gr.Slider(10.0, 300.0,value=130.0,step=5.0, label="MMI length L (µm)")
wmmi_slider = gr.Slider(2.0, 20.0, value=8.0, step=0.5, label="MMI width w_MMI (µm)")
wwg_slider = gr.Slider(0.5, 5.0, value=2.0, step=0.1, label="I/O waveguide width w_wg (µm)")
d_slider = gr.Slider(1.0, 20.0, value=4.0, step=0.5, label="Waveguide separation d (µm)")
# 4) Common parameters
with gr.Column(scale=1):
n_WG_slider = gr.Slider(1.0, 2.0, value=1.1, step=0.01, label="Core refractive index n_WG")
wavelength_slider= gr.Slider(0.4, 1.6, value=0.532,step=0.01, label="Wavelength λ (µm)")
ind_m_slider = gr.Slider(0, 4, value=0, step=1, label="Mode index ind_m")
run_button = gr.Button("Run BPM")
download_button = gr.DownloadButton(label="Download data")
# 5) Plot output
with gr.Column(scale=2):
plot_output = gr.Plot()
# 6) Toggle panels on sim_type change
sim_type.change(
fn=lambda choice: (
gr.update(visible=(choice=="Waveguide S-bend")),
gr.update(visible=(choice=="MMI Splitter"))
),
inputs=sim_type,
outputs=[waveguide_panel, mmi_panel]
)
# 7) Wire up Run button + auto-update
all_inputs = [
sim_type,
w_slider, l_slider, Lb_slider,
z0_slider, Lmmi_slider, wmmi_slider, wwg_slider, d_slider,
n_WG_slider, wavelength_slider, ind_m_slider
]
run_button.click(
fn=run_dispatcher,
inputs=all_inputs,
outputs=[plot_output, download_button]
)
for inp in all_inputs:
inp.change(
fn=run_dispatcher,
inputs=all_inputs,
outputs=[plot_output, download_button]
)
demo.launch()
|