Author: Prof. Tianyu Wang, Boston University
In this notebook, we show how to use Tidy3D to optimize a 2x2 balanced MMI by modifying the boundaries of a structure defined with a PolySlab. This is our first example illustrating inverse design for a multi-output port device with a specified output phase relationship. The epitaxy and device concept follow this paper (with modifications for better performance):
Ma, Yong, Seoijin Park, Liwei Wang, and Seng Tiong Ho. "Ultracompact multimode interference 3-dB coupler with strong lateral confinement by deep dry etching." *IEEE Photonics Technology Letters 12*, no. 5 (2000): 492-494. DOI: 10.1109/68.841263

import matplotlib.pylab as plt
import numpy as np
import autograd as ag
import autograd.numpy as anp
import tidy3d as td
import tidy3d.web as web
Parameters and Materials¶
wg_sep = 0.5
l_MMI = 12.0 # target MMI length
w_wg = 1.0
freq0 = 193414493734202.56 # central frequency for 1550 nm light
fwidth = 6245676208333.328
BCB_medium = td.Medium(
name="BCB",
permittivity=1.45**2,
)
InP = td.Medium(
name="InP",
permittivity=3.167**2,
)
Q1p3_medium = td.Medium(
name="Q1p3",
permittivity=3.41**2,
)
wg_loc = (wg_sep + w_wg) / 2
sim_box_cx = l_MMI / 2
sim_box_cy = 0.0
sim_box_cz = 2.25
sim_box_lx = l_MMI + 3
sim_box_ly = wg_sep + w_wg * 2 + 3
sim_box_lz = 6.5
Make Simulation¶
Define a function that takes y coordinates (parameters to be designed) and returns a simulation object that can be submitted to the server.
def make_sim(ys_half) -> td.Simulation:
# fixed structures
sub = td.Structure(
geometry=td.Box(center=[0, 0, -5], size=[td.inf, td.inf, 10]),
name="sub",
medium=InP,
)
wg1_1 = td.Structure(
geometry=td.Box(center=[-2.5, wg_loc, 0.5], size=[5, w_wg, 1.0]),
name="wg1_1",
medium=InP,
)
wg1_2 = td.Structure(
geometry=td.Box(center=[-2.5, wg_loc, 1.325], size=[5, w_wg, 0.65]),
name="wg1_2",
medium=Q1p3_medium,
)
wg1_3 = td.Structure(
geometry=td.Box(center=[-2.5, wg_loc, 2.1], size=[5, w_wg, 0.9]),
name="wg1_3",
medium=InP,
)
wg2_1 = td.Structure(
geometry=td.Box(center=[-2.5, -wg_loc, 0.5], size=[5, w_wg, 1.0]),
name="wg2_1",
medium=InP,
)
wg2_2 = td.Structure(
geometry=td.Box(center=[-2.5, -wg_loc, 1.325], size=[5, w_wg, 0.65]),
name="wg2_2",
medium=Q1p3_medium,
)
wg2_3 = td.Structure(
geometry=td.Box(center=[-2.5, -wg_loc, 2.1], size=[5, w_wg, 0.9]),
name="wg2_3",
medium=InP,
)
modesource_1 = td.ModeSource(
name="modesource_1",
center=[-1, wg_loc, 1.325],
size=[0, 2, 3.5],
source_time=td.GaussianPulse(
freq0=freq0,
fwidth=fwidth,
),
direction="+",
mode_spec=td.ModeSpec(num_modes=5, filter_pol="te"),
mode_index=0,
)
wg3_1 = td.Structure(
geometry=td.Box(center=[l_MMI + 2.5, wg_loc, 0.5], size=[5, w_wg, 1.0]),
name="wg3_1",
medium=InP,
)
wg3_2 = td.Structure(
geometry=td.Box(center=[l_MMI + 2.5, wg_loc, 1.325], size=[5, w_wg, 0.65]),
name="wg3_2",
medium=Q1p3_medium,
)
wg3_3 = td.Structure(
geometry=td.Box(center=[l_MMI + 2.5, wg_loc, 2.1], size=[5, w_wg, 0.9]),
name="wg3_3",
medium=InP,
)
wg4_1 = td.Structure(
geometry=td.Box(center=[l_MMI + 2.5, -wg_loc, 0.5], size=[5, w_wg, 1.0]),
name="wg4_1",
medium=InP,
)
wg4_2 = td.Structure(
geometry=td.Box(center=[l_MMI + 2.5, -wg_loc, 1.325], size=[5, w_wg, 0.65]),
name="wg4_2",
medium=Q1p3_medium,
)
wg4_3 = td.Structure(
geometry=td.Box(center=[l_MMI + 2.5, -wg_loc, 2.1], size=[5, w_wg, 0.9]),
name="wg4_3",
medium=InP,
)
modemonitor_3 = td.ModeMonitor(
name="modemonitor_3",
center=[l_MMI + 1.0, wg_loc, 1.325], # [l_MMI + 0.1, wg_loc, 0.85],
size=[0, 2, 3.5],
freqs=[freq0],
mode_spec=td.ModeSpec(num_modes=5, filter_pol="te"),
)
modemonitor_4 = td.ModeMonitor(
name="modemonitor_4",
center=[l_MMI + 1.0, -wg_loc, 1.325],
size=[0, 2, 3.5],
freqs=[freq0],
mode_spec=td.ModeSpec(num_modes=5, filter_pol="te"),
)
# Multimode waveguide structure to optimize.
MMI = make_wg(ys_half)
return td.Simulation(
center=[sim_box_cx, sim_box_cy, sim_box_cz],
size=[sim_box_lx, sim_box_ly, sim_box_lz],
grid_spec=td.GridSpec.auto(wavelength=1.55, min_steps_per_wvl=10),
run_time=50 * 1e-12,
medium=BCB_medium,
sources=[modesource_1],
monitors=[modemonitor_3, modemonitor_4],
structures=[
sub,
wg1_1,
wg1_2,
wg1_3,
wg2_1,
wg2_2,
wg2_3,
wg3_1,
wg3_2,
wg3_3,
wg4_1,
wg4_2,
wg4_3,
]
+ MMI,
)
The y coordinates for the MMI slab are defined as a set of points, and make_sim(ys_half) returns the polygon used in the simulation.
# Fixed parameters
num_points = 25
x_start = 0
x_half = l_MMI / 2
xs_half = np.linspace(x_start, x_half, num_points)
# Apply the symmetry
def make_wg(ys_half) -> list[td.Structure]: # ys_half excludes the first point
xs = anp.concatenate([xs_half, xs_half[1:] + x_half])
ys_half = np.concatenate(([wg_sep / 2.0 + w_wg], ys_half))
ys = anp.concatenate([ys_half, ys_half[:-1][::-1]])
vertices = anp.concatenate(
[
anp.column_stack((xs, ys)),
anp.column_stack((xs[::-1], -ys[::-1])),
]
)
MMIs = [
td.Structure(
geometry=td.PolySlab(vertices=vertices, slab_bounds=(0, 1.0), axis=2),
medium=InP,
),
td.Structure(
geometry=td.PolySlab(vertices=vertices, slab_bounds=(1.0, 1.65), axis=2),
medium=Q1p3_medium,
),
td.Structure(
geometry=td.PolySlab(vertices=vertices, slab_bounds=(1.65, 2.55), axis=2),
medium=InP,
),
]
return MMIs
Extract the Output & Post-Processing¶
- Define a function that measures the output intensities (for two ports) and fits them to our target (so the final loss function returns a single value regardless of the number of ports).
- Mathematically, this is equivalent to the L2 loss of the output, treated as an N-dimensional complex vector, compared to the target output values.
def measure_outputs_fit(
sim_data: td.SimulationData,
) -> float: # Smaller values are better.
# For multiple outputs, measure all outputs.
freq0 = sim_data.simulation.monitors[0].freqs[0]
out1amp = (
sim_data["modemonitor_3"]
.amps.sel(direction="+", f=freq0, mode_index=0)
.values.item()
)
out2amp = (
sim_data["modemonitor_4"]
.amps.sel(direction="+", f=freq0, mode_index=0)
.values.item()
)
output_vec = anp.array([out1amp, out2amp])
output_vec *= anp.exp(-1j * anp.angle(out1amp)) # Remove the common phase.
return anp.sum(
anp.abs(
output_vec
- anp.array([1 / anp.sqrt(2), 1 / anp.sqrt(2) * anp.exp(-1j * anp.pi / 2)])
)
** 2
)
# Needs to be an array of size 1; a single scalar does not work.
A function that takes raw parameters (any real number) and smoothly maps them into valid y values (between our self-specified minimum and maximum), along with a function that performs the inverse mapping.
ys_half_min = 0.5
ys_half_max = sim_box_ly / 2 - 1
def get_ys_half(parameters: np.ndarray) -> np.ndarray:
"""Convert arbitrary parameters to y values for the vertices (parameter range (-inf, inf) maps to ys_half range (ys_half_min, ys_half_max))."""
params_between_pm_1 = anp.tanh(np.pi * parameters)
return (params_between_pm_1 + 1) / 2 * (ys_half_max - ys_half_min) + ys_half_min
def get_params(ys_half: np.ndarray) -> np.ndarray:
"""Inverse of the above mapping; recover parameters from ys."""
return (
np.arctanh((ys_half - ys_half_min) * 2 / (ys_half_max - ys_half_min) - 1)
/ np.pi
)
params_test = 2 * (np.random.random((10,)) - 0.5)
ys_test = get_ys_half(params_test)
assert np.allclose(get_params(ys_test), params_test)
def make_sim_params(parameters: np.ndarray) -> td.Simulation:
"""Make the simulation out of raw parameters."""
ys_half = get_ys_half(parameters)
return make_sim(ys_half)
ys_half_0 = anp.linspace((wg_sep + w_wg * 2) / 2, 0.8, num_points - 1) # Initial guess.
params_0 = get_params(ys_half_0)
sim = make_sim_params(params_0)
sim.plot_3d()
Penalty Function¶
- Ensure the device is feasible for fabrication.
- Similar to regularization in neural networks.
from tidy3d.plugins.autograd.invdes import make_curvature_penalty
curvature_penalty = make_curvature_penalty(min_radius=1.0)
def penalty(params: np.ndarray) -> float:
"""Compute penalty for a set of parameters."""
ys = get_ys_half(params)
ys = np.concatenate(([wg_sep / 2.0 + w_wg], ys))
points = anp.array([xs_half, ys]).T
return curvature_penalty(points)
Objective Function¶
The optimizer iteratively minimizes this objective, which combines the output measurement fit and the penalty term.
def objective(params) -> float:
sim = make_sim_params(params)
sim_data = web.run(sim, task_name="tidy3dMMIadj")
print(penalty(params))
print(measure_outputs_fit(sim_data))
return measure_outputs_fit(sim_data) + penalty(params)
grad_fn = ag.value_and_grad(objective)
import optax
import pickle
td.config.logging_level = "ERROR"
# Hyperparameters
num_steps = 15
learning_rate = 0.01
# Initialize the Adam optimizer with the starting parameters.
params = np.array(params_0).copy()
schedule = optax.piecewise_constant_schedule(
init_value=learning_rate, boundaries_and_scales={10: 0.5}
)
optimizer = optax.adam(
learning_rate=schedule,
b1=0.9, # beta1
b2=0.99, # beta2: default 0.999
eps=1e-8,
)
# optimizer = optax.sgd(learning_rate=learning_rate)
opt_state = optimizer.init(params)
# Store history.
objective_history = []
param_history = [params]
for i in range(num_steps):
# Compute the gradient and current objective function value.
value, gradient = grad_fn(params)
# Convert NaNs to 0 (infinite radius of curvature) and multiply all values by -1 to maximize the objective.
# Outputs.
print(f"step = {i + 1}")
print(f"\tJ = {value:.4e}")
print(f"\tgrad_norm = {np.linalg.norm(gradient):.4e}")
# Compute and apply the optimizer updates based on the gradient.
updates, opt_state = optimizer.update(gradient, opt_state, params)
params = optax.apply_updates(params, updates)
params = np.array(params)
# Save history.
objective_history.append(value)
param_history.append(params)
checkpoint = {
"params": params,
"opt_state": opt_state,
"objective_history": objective_history,
"param_history": param_history,
"last_step": num_steps,
}
with open("checkpoint.pkl", "wb") as f:
pickle.dump(checkpoint, f)
15:52:29 -03 Created task 'tidy3dMMIadj' with resource_id 'fdve-c73169d2-d5da-41fa-88ce-48964d6a1e0e' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-c73169d2-d5d a-41fa-88ce-48964d6a1e0e'.
Task folder: 'default'.
Output()
15:52:33 -03 Estimated FlexCredit cost: 1.176. Minimum cost depends on task execution details. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
Output()
15:52:37 -03 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.
Output()
15:52:41 -03 status = preprocess
15:52:46 -03 starting up solver
15:52:47 -03 running solver
Output()
15:52:55 -03 early shutoff detected at 4%, exiting.
15:52:56 -03 status = postprocess
Output()
15:52:59 -03 status = success
15:53:01 -03 View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-c73169d2-d5d a-41fa-88ce-48964d6a1e0e'.
Output()
15:53:05 -03 Loading simulation from simulation_data.hdf5
Autograd ArrayBox with value 1.1914871495818756e-11 Autograd ArrayBox with value 1.0845485202207426
Started working on Batch containing 1 tasks.
15:53:10 -03 Maximum FlexCredit cost: 1.208 for the whole batch.
Use 'Batch.real_cost()' to get the billed FlexCredit cost after completion.
Output()
15:53:37 -03 Batch complete.
Output()
step = 1 J = 1.0845e+00 grad_norm = 7.2962e+00
15:53:39 -03 Created task 'tidy3dMMIadj' with resource_id 'fdve-5c6049e9-a004-438c-9369-ffc6c8f0367d' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-5c6049e9-a00 4-438c-9369-ffc6c8f0367d'.
Task folder: 'default'.
Output()
15:53:42 -03 Estimated FlexCredit cost: 1.176. Minimum cost depends on task execution details. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
Output()
15:53:46 -03 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.
Output()
15:54:31 -03 status = preprocess
15:54:37 -03 starting up solver
running solver
Output()
15:54:50 -03 early shutoff detected at 4%, exiting.
15:54:51 -03 status = postprocess
Output()
15:54:54 -03 status = success
15:54:56 -03 View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-5c6049e9-a00 4-438c-9369-ffc6c8f0367d'.
Output()
15:54:59 -03 Loading simulation from simulation_data.hdf5
Autograd ArrayBox with value 0.0 Autograd ArrayBox with value 0.8062529734229864
Started working on Batch containing 1 tasks.
15:55:05 -03 Maximum FlexCredit cost: 1.208 for the whole batch.
Use 'Batch.real_cost()' to get the billed FlexCredit cost after completion.
Output()
15:57:38 -03 Batch complete.
Output()
step = 2 J = 8.0625e-01 grad_norm = 6.0516e+00
15:57:40 -03 Created task 'tidy3dMMIadj' with resource_id 'fdve-c5b56090-c581-4636-a43e-2358a903aa44' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-c5b56090-c58 1-4636-a43e-2358a903aa44'.
Task folder: 'default'.
Output()
15:57:43 -03 Estimated FlexCredit cost: 1.176. Minimum cost depends on task execution details. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
Output()
15:57:47 -03 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.
Output()
15:59:08 -03 status = preprocess
15:59:13 -03 starting up solver
running solver
Output()
15:59:27 -03 early shutoff detected at 4%, exiting.
15:59:28 -03 status = postprocess
Output()
15:59:31 -03 status = success
15:59:33 -03 View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-c5b56090-c58 1-4636-a43e-2358a903aa44'.
Output()
15:59:36 -03 Loading simulation from simulation_data.hdf5
Autograd ArrayBox with value 1.310412275269257e-11 Autograd ArrayBox with value 0.5603121752719921
15:59:37 -03 Started working on Batch containing 1 tasks.
15:59:43 -03 Maximum FlexCredit cost: 1.208 for the whole batch.
Use 'Batch.real_cost()' to get the billed FlexCredit cost after completion.
Output()
16:00:28 -03 Batch complete.
Output()
step = 3 J = 5.6031e-01 grad_norm = 5.5494e+00
16:00:30 -03 Created task 'tidy3dMMIadj' with resource_id 'fdve-6bef01f7-f407-481b-a1ee-e62926e630ff' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-6bef01f7-f40 7-481b-a1ee-e62926e630ff'.
Task folder: 'default'.
Output()
16:00:34 -03 Estimated FlexCredit cost: 1.176. Minimum cost depends on task execution details. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
Output()
16:00:38 -03 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.
Output()
16:00:50 -03 starting up solver
16:00:51 -03 running solver
Output()
16:01:09 -03 early shutoff detected at 4%, exiting.
16:01:10 -03 status = success
View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-6bef01f7-f40 7-481b-a1ee-e62926e630ff'.
Output()
16:01:13 -03 Loading simulation from simulation_data.hdf5
Autograd ArrayBox with value 0.00010287196003832341 Autograd ArrayBox with value 0.37841807407707767
Started working on Batch containing 1 tasks.
16:01:19 -03 Maximum FlexCredit cost: 1.208 for the whole batch.
Use 'Batch.real_cost()' to get the billed FlexCredit cost after completion.
Output()
16:01:49 -03 Batch complete.
Output()
step = 4 J = 3.7852e-01 grad_norm = 4.1899e+00
16:01:52 -03 Created task 'tidy3dMMIadj' with resource_id 'fdve-43d8518f-8b0d-4a70-82a3-8f1236af0bd9' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-43d8518f-8b0 d-4a70-82a3-8f1236af0bd9'.
Task folder: 'default'.
Output()
16:01:55 -03 Estimated FlexCredit cost: 1.176. Minimum cost depends on task execution details. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
Output()
16:02:00 -03 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.
Output()
16:02:12 -03 starting up solver
16:02:13 -03 running solver
Output()
16:02:24 -03 early shutoff detected at 4%, exiting.
status = postprocess
Output()
16:02:28 -03 status = success
16:02:30 -03 View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-43d8518f-8b0 d-4a70-82a3-8f1236af0bd9'.
Output()
16:02:33 -03 Loading simulation from simulation_data.hdf5
Autograd ArrayBox with value 0.011128271649457282 Autograd ArrayBox with value 0.24685722901208346
Started working on Batch containing 1 tasks.
16:02:39 -03 Maximum FlexCredit cost: 1.208 for the whole batch.
Use 'Batch.real_cost()' to get the billed FlexCredit cost after completion.
Output()
16:06:15 -03 Batch complete.
Output()
step = 5 J = 2.5799e-01 grad_norm = 7.5265e+00
16:06:17 -03 Created task 'tidy3dMMIadj' with resource_id 'fdve-dcd07df4-86ce-4393-ba7e-9b5b7e78317a' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-dcd07df4-86c e-4393-ba7e-9b5b7e78317a'.
Task folder: 'default'.
Output()
16:06:20 -03 Estimated FlexCredit cost: 1.176. Minimum cost depends on task execution details. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
Output()
16:06:24 -03 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.
Output()
16:06:31 -03 status = preprocess
16:06:36 -03 starting up solver
16:06:37 -03 running solver
Output()
16:06:46 -03 early shutoff detected at 4%, exiting.
16:06:47 -03 status = postprocess
Output()
16:06:50 -03 status = success
16:06:52 -03 View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-dcd07df4-86c e-4393-ba7e-9b5b7e78317a'.
Output()
16:06:55 -03 Loading simulation from simulation_data.hdf5
Autograd ArrayBox with value 3.5963767960258645e-07 Autograd ArrayBox with value 0.14899286550021512
Started working on Batch containing 1 tasks.
16:07:01 -03 Maximum FlexCredit cost: 1.208 for the whole batch.
Use 'Batch.real_cost()' to get the billed FlexCredit cost after completion.
Output()
16:07:25 -03 Batch complete.
Output()
step = 6 J = 1.4899e-01 grad_norm = 2.0224e+00
16:07:27 -03 Created task 'tidy3dMMIadj' with resource_id 'fdve-3a6a074c-4a00-4191-ac06-8f499c04196c' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-3a6a074c-4a0 0-4191-ac06-8f499c04196c'.
Task folder: 'default'.
Output()
16:07:30 -03 Estimated FlexCredit cost: 1.176. Minimum cost depends on task execution details. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
Output()
16:07:34 -03 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.
Output()
16:07:39 -03 status = preprocess
16:07:44 -03 starting up solver
running solver
Output()
16:08:00 -03 early shutoff detected at 4%, exiting.
status = postprocess
Output()
16:08:04 -03 status = success
16:08:06 -03 View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-3a6a074c-4a0 0-4191-ac06-8f499c04196c'.
Output()
16:08:09 -03 Loading simulation from simulation_data.hdf5
Autograd ArrayBox with value 1.7070064538075662e-06 Autograd ArrayBox with value 0.1026582001009208
Started working on Batch containing 1 tasks.
16:08:15 -03 Maximum FlexCredit cost: 1.208 for the whole batch.
Use 'Batch.real_cost()' to get the billed FlexCredit cost after completion.
Output()
16:08:41 -03 Batch complete.
Output()
step = 7 J = 1.0266e-01 grad_norm = 1.6868e+00
16:08:43 -03 Created task 'tidy3dMMIadj' with resource_id 'fdve-8af7a8f3-cd72-46d0-b33f-dfee24f4a8f6' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-8af7a8f3-cd7 2-46d0-b33f-dfee24f4a8f6'.
Task folder: 'default'.
Output()
16:08:46 -03 Estimated FlexCredit cost: 1.176. Minimum cost depends on task execution details. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
Output()
16:08:51 -03 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.
Output()
16:08:55 -03 status = preprocess
16:09:00 -03 starting up solver
16:09:01 -03 running solver
Output()
16:09:19 -03 early shutoff detected at 4%, exiting.
16:09:20 -03 status = postprocess
Output()
16:09:21 -03 status = success
16:09:23 -03 View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-8af7a8f3-cd7 2-46d0-b33f-dfee24f4a8f6'.
Output()
16:09:26 -03 Loading simulation from simulation_data.hdf5
Autograd ArrayBox with value 0.0005682527800021411 Autograd ArrayBox with value 0.06247049438086219
Started working on Batch containing 1 tasks.
16:09:32 -03 Maximum FlexCredit cost: 1.208 for the whole batch.
Use 'Batch.real_cost()' to get the billed FlexCredit cost after completion.
Output()
16:09:52 -03 Batch complete.
Output()
step = 8 J = 6.3039e-02 grad_norm = 1.8994e+00
16:09:55 -03 Created task 'tidy3dMMIadj' with resource_id 'fdve-158a2c9d-4aaa-49bd-af41-6b93bae1b97e' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-158a2c9d-4aa a-49bd-af41-6b93bae1b97e'.
Task folder: 'default'.
Output()
16:09:58 -03 Estimated FlexCredit cost: 1.176. Minimum cost depends on task execution details. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
Output()
16:10:02 -03 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.
Output()
16:10:07 -03 status = preprocess
16:10:12 -03 starting up solver
running solver
Output()
16:10:30 -03 early shutoff detected at 4%, exiting.
16:10:31 -03 status = postprocess
Output()
16:10:34 -03 status = success
16:10:36 -03 View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-158a2c9d-4aa a-49bd-af41-6b93bae1b97e'.
Output()
16:10:39 -03 Loading simulation from simulation_data.hdf5
Autograd ArrayBox with value 0.0025670907016877046 Autograd ArrayBox with value 0.025802648174640674
Started working on Batch containing 1 tasks.
16:10:45 -03 Maximum FlexCredit cost: 1.208 for the whole batch.
Use 'Batch.real_cost()' to get the billed FlexCredit cost after completion.
Output()
16:11:14 -03 Batch complete.
Output()
step = 9 J = 2.8370e-02 grad_norm = 2.9723e+00
16:11:17 -03 Created task 'tidy3dMMIadj' with resource_id 'fdve-3948ac76-6fda-4504-9def-8bd506173fe8' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-3948ac76-6fd a-4504-9def-8bd506173fe8'.
Task folder: 'default'.
Output()
16:11:20 -03 Estimated FlexCredit cost: 1.176. Minimum cost depends on task execution details. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
Output()
16:11:24 -03 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.
Output()
16:11:42 -03 starting up solver
running solver
Output()
16:11:54 -03 early shutoff detected at 4%, exiting.
status = postprocess
Output()
16:11:58 -03 status = success
16:12:00 -03 View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-3948ac76-6fd a-4504-9def-8bd506173fe8'.
Output()
16:12:03 -03 Loading simulation from simulation_data.hdf5
Autograd ArrayBox with value 0.00011907159155895129 Autograd ArrayBox with value 0.008102693176776206
Started working on Batch containing 1 tasks.
16:12:09 -03 Maximum FlexCredit cost: 1.208 for the whole batch.
Use 'Batch.real_cost()' to get the billed FlexCredit cost after completion.
Output()
16:13:02 -03 Batch complete.
Output()
step = 10 J = 8.2218e-03 grad_norm = 4.5009e-01
16:13:04 -03 Created task 'tidy3dMMIadj' with resource_id 'fdve-d8a2e404-c3fd-434b-8c2f-6e7963b0782e' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-d8a2e404-c3f d-434b-8c2f-6e7963b0782e'.
Task folder: 'default'.
Output()
16:13:07 -03 Estimated FlexCredit cost: 1.176. Minimum cost depends on task execution details. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
Output()
16:13:11 -03 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.
Output()
16:13:46 -03 status = preprocess
16:13:52 -03 starting up solver
running solver
Output()
16:14:11 -03 early shutoff detected at 4%, exiting.
status = postprocess
Output()
16:14:15 -03 status = success
16:14:17 -03 View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-d8a2e404-c3f d-434b-8c2f-6e7963b0782e'.
Output()
16:14:20 -03 Loading simulation from simulation_data.hdf5
Autograd ArrayBox with value 0.002349891506344505 Autograd ArrayBox with value 0.003916633263534279
Started working on Batch containing 1 tasks.
16:14:26 -03 Maximum FlexCredit cost: 1.208 for the whole batch.
Use 'Batch.real_cost()' to get the billed FlexCredit cost after completion.
Output()
16:15:11 -03 Batch complete.
Output()
step = 11 J = 6.2665e-03 grad_norm = 2.7466e+00
16:15:14 -03 Created task 'tidy3dMMIadj' with resource_id 'fdve-a6ed8466-0ab2-454a-ba98-d0bdfd6858dd' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-a6ed8466-0ab 2-454a-ba98-d0bdfd6858dd'.
Task folder: 'default'.
Output()
16:15:17 -03 Estimated FlexCredit cost: 1.176. Minimum cost depends on task execution details. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
Output()
16:15:20 -03 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.
Output()
16:15:29 -03 status = preprocess
16:15:35 -03 starting up solver
running solver
Output()
16:15:46 -03 early shutoff detected at 4%, exiting.
16:15:47 -03 status = success
View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-a6ed8466-0ab 2-454a-ba98-d0bdfd6858dd'.
Output()
16:15:50 -03 Loading simulation from simulation_data.hdf5
Autograd ArrayBox with value 0.0003520986322037858 Autograd ArrayBox with value 0.004899877599120619
16:15:51 -03 Started working on Batch containing 1 tasks.
16:15:56 -03 Maximum FlexCredit cost: 1.208 for the whole batch.
Use 'Batch.real_cost()' to get the billed FlexCredit cost after completion.
Output()
16:16:23 -03 Batch complete.
Output()
step = 12 J = 5.2520e-03 grad_norm = 6.3671e-01
16:16:25 -03 Created task 'tidy3dMMIadj' with resource_id 'fdve-dac97da6-64a9-46d4-b078-f80977589ce2' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-dac97da6-64a 9-46d4-b078-f80977589ce2'.
Task folder: 'default'.
Output()
16:16:29 -03 Estimated FlexCredit cost: 1.176. Minimum cost depends on task execution details. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
Output()
16:16:32 -03 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.
Output()
16:16:48 -03 starting up solver
running solver
Output()
16:17:07 -03 early shutoff detected at 4%, exiting.
status = postprocess
Output()
16:17:11 -03 status = success
16:17:13 -03 View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-dac97da6-64a 9-46d4-b078-f80977589ce2'.
Output()
16:17:16 -03 Loading simulation from simulation_data.hdf5
Autograd ArrayBox with value 0.00011586847629584113 Autograd ArrayBox with value 0.0078057860869055334
Started working on Batch containing 1 tasks.
16:17:22 -03 Maximum FlexCredit cost: 1.208 for the whole batch.
Use 'Batch.real_cost()' to get the billed FlexCredit cost after completion.
Output()
16:17:44 -03 Batch complete.
Output()
step = 13 J = 7.9217e-03 grad_norm = 6.0158e-01
16:17:46 -03 Created task 'tidy3dMMIadj' with resource_id 'fdve-65dbff02-c404-4d86-89ce-99a952761ec6' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-65dbff02-c40 4-4d86-89ce-99a952761ec6'.
Task folder: 'default'.
Output()
16:17:50 -03 Estimated FlexCredit cost: 1.176. Minimum cost depends on task execution details. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
Output()
16:17:54 -03 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.
Output()
16:18:40 -03 status = preprocess
16:18:45 -03 starting up solver
16:18:46 -03 running solver
Output()
16:19:03 -03 early shutoff detected at 4%, exiting.
16:19:04 -03 status = postprocess
Output()
16:19:08 -03 status = success
16:19:10 -03 View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-65dbff02-c40 4-4d86-89ce-99a952761ec6'.
Output()
16:19:12 -03 Loading simulation from simulation_data.hdf5
Autograd ArrayBox with value 0.00025578170972243784 Autograd ArrayBox with value 0.012093082778784616
16:19:13 -03 Started working on Batch containing 1 tasks.
16:19:27 -03 Maximum FlexCredit cost: 1.208 for the whole batch.
Use 'Batch.real_cost()' to get the billed FlexCredit cost after completion.
Output()
16:19:54 -03 Batch complete.
Output()
step = 14 J = 1.2349e-02 grad_norm = 9.2290e-01
16:19:56 -03 Created task 'tidy3dMMIadj' with resource_id 'fdve-cdfa82e1-3be3-46e8-8b5a-e26b91d43291' and task_type 'FDTD'.
View task using web UI at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-cdfa82e1-3be 3-46e8-8b5a-e26b91d43291'.
Task folder: 'default'.
Output()
16:20:08 -03 Estimated FlexCredit cost: 1.176. Minimum cost depends on task execution details. Use 'web.real_cost(task_id)' to get the billed FlexCredit cost after a simulation run.
Output()
16:20:12 -03 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.
Output()
16:20:16 -03 status = preprocess
16:20:21 -03 starting up solver
16:20:22 -03 running solver
Output()
16:20:33 -03 early shutoff detected at 4%, exiting.
status = success
View simulation result at 'https://tidy3d.simulation.cloud/workbench?taskId=fdve-cdfa82e1-3be 3-46e8-8b5a-e26b91d43291'.
Output()
16:20:36 -03 Loading simulation from simulation_data.hdf5
Autograd ArrayBox with value 0.00046923602303622434 Autograd ArrayBox with value 0.016732958016607083
Started working on Batch containing 1 tasks.
16:20:43 -03 Maximum FlexCredit cost: 1.208 for the whole batch.
Use 'Batch.real_cost()' to get the billed FlexCredit cost after completion.
Output()
16:21:12 -03 Batch complete.
Output()
step = 15 J = 1.7202e-02 grad_norm = 1.2442e+00
params_best = param_history[-1]
ax = plt.plot(objective_history)
plt.xlabel("iteration number")
plt.ylabel("objective function")
plt.show()
We observe that the objective function decreases, indicating that adjoint optimization improves the MMI performance over successive iterations. The device is also more compact than the one reported in the reference, underscoring the power of inverse design.
sim_best = make_sim_params(param_history[-1])
ax = sim_best.plot(z=0.01)
plt.show()