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