A grating coupler (GC) is a key photonic device used to couple light between optical fibers and on-chip waveguides by diffracting light at a specific angle. These devices often employ apodization, a technique that modifies the grating tooth parameters along the device length to improve efficiency and minimize reflection losses.
In this notebook, we will use gradient-based optimization to determine the optimal grating tooth distribution. We start from a uniform grating coupler and modify the tooth and gap sizes simultaneously using gradient based optimization. Feature size constraints on the parameters enable the device to remain fabricable over the course of optimization. In just a handful of iterations, we achieve a design that outperforms an apodized grating coupler designed using semi-analytical methods.
While the simulations are performed using a 2D cross section, the same approach can be modified to 3D without much further complication.
If you are interested in other inverse design examples using tidy3d, you can find many of them here.
# as we are using autograd to perform gradient calculations, we need to import numpy from autograd's wrapperimport autograd as agimport autograd.numpy as npimport matplotlib.pyplot as pltimport tidy3d as tdimport tidy3d.web as web# we will use Tidy3D's built-in Adam helper to perform the optimizationfrom tidy3d.plugins.autograd import adam, apply_updates
Basic Parameters
First, we define the basic parameters used to define a uniform grating coupler for operation primarily in the C-band.
lda0 =1.55# central wavelengthn_ldas =101# number of wavelength pointsldas = np.linspace(1.5, 1.6, n_ldas) # wavelength rangefreq0 = td.C_0 / lda0 # central frequencyfreqs = td.C_0 / ldas # frequency rangenum_freqs_objective =5ldas_objective = np.linspace(1.5, 1.6, num_freqs_objective)freqs_objective = td.C_0 / ldas_objectivefwidth =0.5* (np.max(freqs) - np.min(freqs)) # width of the source frequency range
The material platform is the common silicon on insulator (SOI) with a 260 nm silicon thickness and 2 µm BOX thickness. The top cladding layer is 680 nm oxide. The grating will be partially etched with an etching depth of 160 nm.
# define materials from the material librarysi = td.material_library["cSi"]["Palik_LowLoss"]sio2 = td.material_library["SiO2"]["Palik_LowLoss"]t_si =0.26# thickness of the silicon layeretch_depth =0.16# etching deptht_tox =0.68# top oxide layer thicknesst_box =2# bottom oxide layer thickness
We aim to design the GC for the standard single-mode fiber (SMF) with a mode field diameter (MFD) of 10.8 µm. The fiber is tilted at a 14.5 degree angle.
theta = np.deg2rad(14.5) # fiber tilt anglemfd =10.8# mode field diametersource_x =4.5# x position of the fiberN =16# number of grating teeth to createinf_eff =1e3# effective infinitybuffer=1.1* lda0 # buffer spacing to pad the simulation domain
Next we compute the uniform tooth parameters (periodicity and fill fraction) to maximize efficiency.
neff_unetch =2.9# effective index of the slab mode of the unetched waveguideneff_etch =2.2# effective index of the slab mode of the etched waveguiden_c =1.44# refractive index of the cladding (SiO2)theta_c = np.sin(theta) / n_c # incident angle in the claddingdef get_periodicity(fill_fraction: float) ->float:"""periodicity (bragg condition) as function of fill fraction, angle, wavelength, and etching parameters."""return lda0 / ( fill_fraction * neff_unetch + (1- fill_fraction) * neff_etch - n_c * np.sin(theta_c) )f0 =0.80periodicity = get_periodicity(f0)p_list = N * [periodicity]f_list = N * [f0]
After obtaining \(p_{\text{i}}\) and \(f_{\text{i}}\), we will write a function to return the width of each air gap and each tooth. We will use these gap widths as the parameters for our design. The advantage is that we can impose bounds on these values to ensure the minimal feature size is above the fabrication constraint.
Here we aim to have a minimal feature size above 60 nm. The current design has a minimal feature size right above it.
def get_widths(p_list, f_list):# calculate the widths of air gaps and silicon teethreturn np.array([item for p, f inzip(p_list, f_list) for item in [p * (1- f), p * f]])widths = get_widths(p_list, f_list)l_grating = np.sum(widths) +3* lda0 # total length of the GC# print the current minimal feature sizeprint(f"The minimal feature size is {1e3* np.min(widths):.2f} nm.")
The minimal feature size is 123.46 nm.
To ensure the minimal feature size is maintained during the optimization, we will use a design parameter in the range from -inf to inf and project it to a tanh function that is bounded by the minimal and maximal feature sizes.
min_width =0.08# minimal feature size we want to maintainmax_width =1# maximal feature size# function to project a design parameter between -inf to inf to between min_width and max_widthdef project(x):return0.5* (max_width - min_width) * np.tanh(x) +0.5* (max_width + min_width)# function to inversely project a design parameter between min_width and max_width to between -inf to infdef inverse_project(y):return np.arctanh((2* (y -0.5* (max_width + min_width))) / (max_width - min_width))# project the widths to parameters between -inf to infparams0 = inverse_project(widths)
Define Static Components of the Simulation
Next we will define the components that don’t change during the optimization. These include the cladding layer, the output waveguide, the unetched layer, the bottom oxide layer, and the silicon substrate.
The source and monitor are not changed either. We use a GaussianBeam to represent the incident fiber mode. A ModeMonitor is placed at the output waveguide to measure the coupling efficiency.
gap =1# gap size between the source plane and the top surface of the cladding# define a gaussian beam sourcesource = td.GaussianBeam( size=(2* mfd, td.inf, 0), center=[source_x, 0, t_tox + gap], source_time=td.GaussianPulse(freq0=freq0, fwidth=fwidth), angle_theta=theta, direction="-", waist_radius=mfd /2, pol_angle=np.pi /2, # 90 degree polarization angle for TE polarization)# define a mode monitormode_monitor = td.ModeMonitor( center=(-buffer/2, 0, t_si /2), size=(0, td.inf, 6* t_si), freqs=freqs, mode_spec=td.ModeSpec(num_modes=1, target_neff=3), name="mode",)
Simulate the Designed Apodized GC
To simulate the designed GC and facility future optimization, we define a function that takes in an array of design parameters and returns a Simulation object. Note again that each design parameter has a range from -inf to inf. It will then be projected to a range between min_width and max_width.
def make_2d_sim(design_parameters):# calculate the widths of air gaps and silicon teeth widths_si = project(design_parameters[1::2]) widths_air = project(design_parameters[::2])# initialize the center and size of each silicon teeth center =0 size =0# create the grating geometries from the given widths gratings =0for width_si, width_air inzip(widths_si, widths_air): center += width_air + width_si /2 size = width_si gratings += td.Box( center=(center, 0, t_si - etch_depth /2), size=(size, td.inf, etch_depth) ) center += width_si /2# create the grating structure gratings = td.Structure(geometry=gratings, medium=si)# create a box to represent the simulation domain box sim_box = td.Box.from_bounds( rmin=(-buffer, 0, -t_box -buffer/2), rmax=(l_grating +buffer, 0, t_si +buffer), ) run_time =1e-12# simulation run time# construct simulation sim = td.Simulation( center=sim_box.center, size=sim_box.size, grid_spec=td.GridSpec.auto( min_steps_per_wvl=30, wavelength=lda0 ), # use a fine grid to ensure the small features are well resolved structures=[ mask, tox, gratings, unetched_waveguide, slab_waveguide, box, substrate, ], sources=[source], monitors=[mode_monitor], medium=sio2, run_time=run_time, boundary_spec=td.BoundarySpec( x=td.Boundary.pml(), y=td.Boundary.periodic(), # set the boundary to periodic in y since it's a 2D simulation z=td.Boundary.pml(), ), )return sim
Create the simulation for the designed apodized GC and visualize it.
08:08:32 UTC Estimated FlexCredit cost: 0.025. This assumes the FDTD solver runs
for the full simulation time; if early shutoff is reached, the
billed cost can be lower. Use 'web.real_cost(task_id)' to get the
billed FlexCredit cost after a simulation run.
08:08:35 UTC status = queued
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:08:47 UTC starting up solver
08:08:48 UTC running solver
08:08:53 UTC early shutoff detected at 47%, exiting.
08:08:54 UTC Loading results from simulation_data.hdf5
Result Visualization
After the simulation is done, we can extract the coupling efficiency from the mode monitor data. In addition, we also calculate two important metrics: the maximum coupling efficiency and the 1dB bandwidth. The maximal coupling efficiency is about 2.7dB and the 1dB bandwidth is about 36 nm.
# function to calculate the coupling efficiency from simulation datadef compute_ce(sim_data): amp = sim_data["mode"].amps.sel(mode_index=0, direction="-").values ce = np.abs(amp) **2# transmission to the top waveguidereturn cedef dB(ce):return10* np.log10(ce)# calculate the coupling efficiency for the designed GCce0 = compute_ce(sim_data0)# plot the coupling efficiencyplt.plot(ldas, dB(ce0), c="red", linewidth=2)plt.xlim(min(ldas), max(ldas))plt.ylim(-10, 0)plt.xlabel("Wavelength (µm)")plt.ylabel("Coupling efficiency (dB)")plt.grid()plt.show()# function to calculate the 1dB bandwidth from the coupling efficiencydef bandwidth(ldas, ce): max_ce = np.max(dB(ce)) threshold = max_ce -1 within_1db = np.where(dB(ce) >= threshold)[0] lambda_min = ldas[within_1db[0]] lambda_max = ldas[within_1db[-1]] bandwidth = lambda_max - lambda_minreturn1e3* bandwidth# print the maximum coupling efficiency and 1dB bandwidthprint(f"The 1dB bandwidth is {bandwidth(ldas, ce0):.1f} nm")print(f"The maximum coupling efficiency is {np.max(dB(ce0)):.2f} dB.")
The 1dB bandwidth is 36.0 nm
The maximum coupling efficiency is -2.74 dB.
Optimize GC with Inverse Design to Maximize the Efficiency and Bandwidth
In this part, we will apply inverse design to maximize the coupling efficiency of our coupling over the wavelength range from 1500 to 1600 nm.
To do this, we need to express our objective as a function of our parameters returning a single float value to maximize. This function will involve constructing, running, and postprocessing our simulation.
def J(design_parameters: np.ndarray) ->float: sim = make_2d_sim(design_parameters) sim_data = web.run(sim, task_name="GC_invdes", verbose=True) ce = np.sum(compute_ce(sim_data)) / n_ldasreturn ce
dJ = ag.value_and_grad(J)
Before running the optimization, we can check the value and gradient of the initial design to ensure the gradient tracking is working properly.
%%timeval, grad = dJ(params0)print(val)print(grad)
08:08:55 UTC Created task 'GC_invdes' with resource_id
'fdve-0aa7ca50-bcef-42c7-92e6-e759db293886' and task_type 'FDTD'.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:09:13 UTC starting up solver
running solver
08:09:19 UTC early shutoff detected at 47%, exiting.
We will use the Adam optimizer to adjust the parameters for a number of iterations until we achieve a good performance.
%%time# hyperparametersnum_steps =25learning_rate =0.05# initialize adam optimizer with starting parametersparams = params0optimizer = adam(learning_rate=learning_rate)opt_state = optimizer.init(params)# store historyJ_history = []params_history = []for i inrange(num_steps):# compute gradient and current objective function value value, gradient = dJ(params)# outputsprint(f"step = {i +1}")print(f"\tJ = {value:.3e}")print(f"\tgrad_norm = {np.linalg.norm(gradient):.4e}")# compute and apply updates to the optimizer based on gradient (-1 sign to maximize obj_fn) updates, opt_state = optimizer.update(-gradient, opt_state, params) params[:] = apply_updates(params, updates)# save history J_history.append(value) params_history.append(params.copy())
08:09:56 UTC Created task 'GC_invdes' with resource_id
'fdve-dff112db-b705-4a4e-bb41-bf77e6896cac' and task_type 'FDTD'.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:10:16 UTC starting up solver
running solver
08:10:20 UTC early shutoff detected at 47%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:11:27 UTC status = preprocess
08:11:31 UTC starting up solver
08:11:32 UTC running solver
08:11:35 UTC early shutoff detected at 48%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:12:36 UTC starting up solver
running solver
08:12:42 UTC early shutoff detected at 47%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:13:33 UTC status = preprocess
08:13:38 UTC starting up solver
running solver
08:13:42 UTC early shutoff detected at 46%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:14:37 UTC status = preprocess
08:14:42 UTC starting up solver
running solver
08:14:47 UTC early shutoff detected at 45%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:17:11 UTC starting up solver
running solver
08:17:16 UTC early shutoff detected at 47%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:18:10 UTC status = preprocess
08:18:14 UTC starting up solver
08:18:15 UTC running solver
08:18:20 UTC early shutoff detected at 47%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:19:11 UTC status = preprocess
08:19:16 UTC starting up solver
running solver
08:19:20 UTC early shutoff detected at 45%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:20:16 UTC starting up solver
running solver
08:20:21 UTC early shutoff detected at 43%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:21:21 UTC starting up solver
08:21:22 UTC running solver
08:21:27 UTC early shutoff detected at 43%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:22:21 UTC starting up solver
08:22:22 UTC running solver
08:22:27 UTC early shutoff detected at 43%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:23:28 UTC starting up solver
running solver
08:23:34 UTC early shutoff detected at 42%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:24:27 UTC status = preprocess
08:24:32 UTC starting up solver
running solver
08:24:36 UTC early shutoff detected at 42%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:25:31 UTC starting up solver
running solver
08:25:37 UTC early shutoff detected at 42%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:27:25 UTC status = preprocess
08:27:29 UTC starting up solver
08:27:30 UTC running solver
08:27:32 UTC early shutoff detected at 42%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:28:34 UTC status = preprocess
08:28:38 UTC starting up solver
08:28:39 UTC running solver
08:28:41 UTC early shutoff detected at 41%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:29:31 UTC status = preprocess
08:29:36 UTC starting up solver
running solver
08:29:40 UTC early shutoff detected at 41%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:31:31 UTC status = preprocess
08:31:35 UTC starting up solver
running solver
08:31:41 UTC early shutoff detected at 41%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:32:38 UTC starting up solver
running solver
08:32:44 UTC early shutoff detected at 42%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:33:41 UTC starting up solver
running solver
08:33:47 UTC early shutoff detected at 41%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:34:41 UTC starting up solver
running solver
08:34:48 UTC early shutoff detected at 41%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:35:40 UTC status = preprocess
08:35:44 UTC starting up solver
running solver
08:35:50 UTC early shutoff detected at 41%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:36:41 UTC status = preprocess
08:36:47 UTC starting up solver
08:36:48 UTC running solver
08:36:51 UTC early shutoff detected at 42%, exiting.
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:37:48 UTC starting up solver
running solver
08:37:54 UTC early shutoff detected at 41%, exiting.
Plot the objective function (average coupling efficiency) as a function of the number of iterations. A steady increase of the average coupling efficiency is observed.
plt.plot(J_history, c="black")plt.xlabel("Iterations")plt.ylabel("Objective function (average coupling efficiency)")plt.show()
Design the Apodized GC
For comparison with more established methods, we’ll simulate a device designed using the approach introduced in the reference paper. First of all, the Bragg condition is given by
where \(p_{\text{i}}\) is the local period of the grating, \(\lambda_\text{c}\) is the central wavelength, \(n_{\text{c}}\) is the refractive index of the cladding, \(\theta_{\text{c}}\) is the incident angle in the cladding (~ 10 degrees from Snell’s law), and
Here \(f_\text{i}\) is the local filling fraction, \(n_\text{neff,unetch}\) is the effective index of the slab mode of the unetched waveguide (260 nm thick), and \(n_\text{neff,etch}\) is the effective index of the slab mode of the etched waveguide (100 nm thick). \(n_\text{neff,unetch}\) and \(n_\text{neff,etch}\) are determined to be about 2.9 and 2.2 by mode analysis (not shown). Furthermore, we follow a linear apodization, namely
\[
f_\text{i} = f_\text{0} - R \times x,
\]
where \(f_\text{0}\) is the filling fraction of the first period, \(R\) is the linear apodization factor and \(x\) is the position of each tooth from the starting point of the grating. By using an initial local filling fraction \(f_\text{0}\)=0.9 and apodization factor \(R\)=0.0025 µm\(^{-1}\) we can recursively calculate \(p_{\text{i}}\) and \(f_\text{i}\) for \(i=0, 1, ..., N-1\) using the equations above. The result is a grating with apodized pitch length and filling fraction.
For more details on the design principles, refer to the reference paper.
# and then the apodized design parameters to compare to laterR =0.025# linear apodization factorp_list_apodized = [] # list to store all local periodicitiesf_list_apodized = [] # list to store all local filling fractionsf0_apodized =0.86# filling fraction of the first teethf_current = f0_apodized # variable to store the current local filling fraction# recursively calculate all local periodicities and filling fractionsfor i inrange(N): p_current = get_periodicity(f_current) p_list_apodized.append(p_current) f_list_apodized.append(f_current) f_current = f0_apodized - R *sum(p_list_apodized)widths_apodized = get_widths(p_list_apodized, f_list_apodized)params_apodized = inverse_project(widths_apodized)sim_apodized = make_2d_sim(params_apodized)
Let’s plot all of the simulations together to see how their features compare.
08:38:57 UTC Estimated FlexCredit cost: 0.025. This assumes the FDTD solver runs
for the full simulation time; if early shutoff is reached, the
billed cost can be lower. Use 'web.real_cost(task_id)' to get the
billed FlexCredit cost after a simulation run.
08:38:58 UTC status = queued
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:39:12 UTC status = preprocess
08:39:16 UTC starting up solver
08:39:17 UTC running solver
08:39:20 UTC early shutoff detected at 42%, exiting.
08:39:25 UTC Estimated FlexCredit cost: 0.025. This assumes the FDTD solver runs
for the full simulation time; if early shutoff is reached, the
billed cost can be lower. Use 'web.real_cost(task_id)' to get the
billed FlexCredit cost after a simulation run.
08:39:31 UTC status = queued
To cancel the simulation, use 'web.abort(task_id)' or
'web.delete(task_id)' or abort/delete the task in the web UI.
Terminating the Python script will not stop the job running on the
cloud.
08:39:43 UTC starting up solver
running solver
08:39:48 UTC early shutoff detected at 42%, exiting.
We see that the optimized and apodized designs both exceed that of the uniform with -2dB efficiency. However, the optimized design far outperforms in terms of bandwidth. We can also confirm that the minimal feature size is maintained above 85 nm.
print("Uniform:")print(f" The 1dB bandwidth is {bandwidth(ldas, ce0):.1f} nm")print(f" The maximum coupling efficiency is {np.max(dB(ce0)):.2f} dB.")print(f" The minimal feature size is {1e3* np.min(project(params0)):.2f} nm.")print("")print("Apodized:")print(f" The 1dB bandwidth is {bandwidth(ldas, ce_apodized):.1f} nm")print(f" The maximum coupling efficiency is {np.max(dB(ce_apodized)):.2f} dB.")print(f" The minimal feature size is {1e3* np.min(project(params_apodized)):.2f} nm.")print("")print("Optimized:")print(f" The 1dB bandwidth is {bandwidth(ldas, ce_opt):.1f} nm")print(f" The maximum coupling efficiency is {np.max(dB(ce_opt)):.2f} dB.")print(f" The minimal feature size is {1e3* np.min(project(params_opt)):.2f} nm.")
Uniform:
The 1dB bandwidth is 36.0 nm
The maximum coupling efficiency is -2.74 dB.
The minimal feature size is 86.12 nm.
Apodized:
The 1dB bandwidth is 43.0 nm
The maximum coupling efficiency is -1.99 dB.
The minimal feature size is 85.00 nm.
Optimized:
The 1dB bandwidth is 50.0 nm
The maximum coupling efficiency is -1.99 dB.
The minimal feature size is 86.12 nm.
Take the Model Further
In this notebook, we only perform 2D simulations. A good next step would be to convert the 2D design to a 3D linear GC or focusing GC. The coupling efficiency of the 3D GC is likely slightly lower than that in 2D. Inverse design can then be applied to fine-tune it again. To minimize the footprint, one can potentially also apply shape optimization to design a compact and low-loss taper section, as demonstrated in this example.
Further visualizations
In case you would like to gain more insight into how your device has changed over optimization, the following are a few post-processing steps to make animations and visualize the grating teeth locations.
We use necessary cookies to run this website. With your permission, we
also use analytics cookies to understand site usage and marketing
cookies for advertising, retargeting, and HubSpot tracking.
Learn more about our cookie policy.
Privacy choices
Choose which optional cookies Flexcompute may use. Necessary cookies
are always on because they support core website behavior, security, and
saving your consent record.
Your browser is sending a Global Privacy Control signal, so marketing
cookies are disabled.
Subscribe
Thanks for subscribing
Publish Your Notebook
Thank you for publishingA confirmation email has been sent to your inbox. Your notebook will be available within the next 48 hours.
Community Library
TERMS & CONDITIONS
EFFECTIVE DATE: January 1, 2025
Terms and Conditions for User-Submitted Content
By submitting content to Flexcompute, you agree to the following terms:
1. Ownership and Copyright
All content, including but not limited to text, data, images, and other materials submitted by users,
remains the sole property of the original creator. Flexcompute does not claim ownership of the submitted
content or any intellectual property rights associated with it.
Users affirm that they own the copyright or have obtained all necessary permissions for the submitted
content and are fully responsible for ensuring that their submissions do not infringe on any third-party
rights.
2. Responsibility for Content
Users are solely responsible for the content they submit. Flexcompute does not endorse, guarantee,
or verify the accuracy, legality, or appropriateness of any submitted content. Users are responsible
for ensuring that their content complies with all applicable laws and regulations.
Users declare that they have obtained authorization from all co-authors and collaborators associated
with the submitted content, granting them the right to submit and sign on behalf of all contributors.
Users agree not to submit content that is illegal, defamatory, obscene, or violates the rights
of others, including privacy and intellectual property rights.
3. Modification and Presentation
Flexcompute reserves the right to review, edit, or modify submitted content to improve clarity,
formatting, and presentation while maintaining the original intent and message.
These modifications are made to enhance the overall quality and readability of the published material.
Users acknowledge that Flexcompute may format or present the content in a way
that aligns with our editorial and visual standards.
4. Liability Disclaimer
Flexcompute shall not be held liable for any disputes arising from user-submitted content, including
but not limited to copyright claims, inaccuracies, or damages resulting from the publication of user content.
Users agree to indemnify Flexcompute against any claims or legal actions resulting from their submitted content.
5. Content Use Rights
By submitting content, users grant Flexcompute a non-exclusive, royalty-free, worldwide license to publish, distribute,
and promote the content for the purposes of showcasing user contributions and marketing our services.
This license does not transfer ownership of the content or any copyright to Flexcompute.
Users retain the right to withdraw their submissions at any time.
Upon request, Flexcompute will remove the content from its platform.
6. Privacy and Confidentiality
Users acknowledge that submitted content may be publicly accessible and therefore waive any
rights to confidentiality or privacy regarding the published material.
Flexcompute will not share personal information of users without
their consent, in accordance with our privacy policy.
Community Library
How the process works:
You submit your notebook.
You will get a permanent URL to promote your work.
Cite the URL as a reference for others in your upcoming papers to enhance the impact.
When someone clicks your URL, your notebook will be displayed.
Enter your email address below to receive the presentation slides. In the future, we’ll share you very few emails when we have new tutorial release, development updates, valuable toolkits and technical guidance . You can unsubscribe at any time by clicking the link at the bottom of every email. We’ll never share your information.