plt.rc("figure", facecolor="white")
plt.rcParams["axes.grid"] = True
plt.rcParams["grid.alpha"] = 0.25
design_labels = {
"single": "Single layer",
"reflector": "With reflector",
}
design_colors = {
"single": "black",
"reflector": "tab:red",
}
design_markers = {
"single": "o",
"reflector": "s",
}
def plot_design_cross_section(params_phys, ax, color, title, include_reflector=False):
starts, ends = compute_grating_edges(params_phys)
structure_start_x = float(starts[0])
structure_end_x = compute_grating_extent(params_phys)
left_limit = min(-5.0, structure_start_x - 0.5)
right_limit = structure_end_x + 0.5
plot_bottom_z = -1.05
oxide_top_z = -0.5 * h_si
ax.add_patch(
plt.Rectangle(
(left_limit, plot_bottom_z),
right_limit - left_limit,
oxide_top_z - plot_bottom_z,
facecolor="lightskyblue",
edgecolor="black",
linewidth=0.8,
alpha=0.35,
)
)
ax.add_patch(
plt.Rectangle(
(left_limit, -0.5 * h_si),
-left_limit,
h_si,
facecolor=(0.83, 0.83, 0.83),
edgecolor="black",
linewidth=1.0,
alpha=0.8,
)
)
ax.add_patch(
plt.Rectangle(
(structure_start_x, -0.5 * h_si),
structure_end_x - structure_start_x,
0.5 * h_si,
facecolor=color,
edgecolor="black",
linewidth=1.0,
alpha=0.25,
)
)
for x_start, x_end in zip(starts, ends):
ax.add_patch(
plt.Rectangle(
(float(x_start), 0.0),
float(x_end - x_start),
0.5 * h_si,
facecolor=color,
edgecolor="black",
linewidth=1.0,
alpha=0.85,
)
)
if include_reflector:
period = float(params_phys["reflector_period"])
duty_cycle = float(params_phys["reflector_duty_cycle"])
tooth_width = period * duty_cycle
n_reflector_periods = num_reflector_periods_to_cover(
params_phys, structure_end_x
)
reflector_top_z = -0.5 * h_si - reflector_gap
reflector_bottom_z = reflector_top_z - reflector_thickness
for start in np.arange(n_reflector_periods) * period:
if start > right_limit:
break
ax.add_patch(
plt.Rectangle(
(float(start), reflector_bottom_z),
tooth_width,
reflector_thickness,
facecolor="tab:orange",
edgecolor="black",
linewidth=0.8,
alpha=0.8,
)
)
ax.axvline(float(params_phys["x_center"]), color="black", linestyle="--", linewidth=1.0)
ax.set_title(title)
ax.set_xlabel("x [um]")
ax.set_ylabel("z [um]")
ax.set_xlim(left_limit, right_limit)
ax.set_ylim(plot_bottom_z, 0.75 * h_si)
ax.set_aspect("equal")
def plot_history(ax, history, title):
objective_history = history["objective"]
grad_norm_history = history["grad_norm"]
steps = np.arange(1, len(objective_history) + 1)
objective_line = ax.plot(
steps, objective_history, color="black", linewidth=2, label="Objective"
)
ax.set_title(title)
ax.set_xlabel("Optimization step")
ax.set_ylabel("Objective")
ax.tick_params(axis="y", labelcolor="black")
grad_steps = np.arange(1, len(grad_norm_history) + 1)
ax_grad = ax.twinx()
grad_line = ax_grad.plot(
grad_steps,
grad_norm_history,
color="tab:orange",
linestyle="--",
linewidth=2,
label="Gradient norm",
)
ax_grad.set_ylabel("Gradient norm", color="tab:orange")
ax_grad.tick_params(axis="y", labelcolor="tab:orange")
lines = objective_line + grad_line
ax.legend(lines, [line.get_label() for line in lines], loc="best")
def plot_width_comparison(design_params, title="Optimized top grating widths"):
fig, ax = plt.subplots(figsize=(12, 3.8), constrained_layout=True)
period_indices = np.arange(1, n_periods + 1)
for design_key, params_phys in design_params.items():
color = design_colors[design_key]
ax.plot(
period_indices,
params_phys["teeth"],
color=color,
linewidth=2,
marker=design_markers[design_key],
label=f"{design_labels[design_key]} teeth",
)
ax.plot(
period_indices,
params_phys["trenches"],
color=color,
linewidth=2,
linestyle="--",
marker=design_markers[design_key],
markerfacecolor="white",
label=f"{design_labels[design_key]} gaps",
)
ax.set_title(title)
ax.set_xlabel("Grating period index")
ax.set_ylabel("Width [um]")
ax.set_xticks(period_indices)
ax.legend(ncol=2, fontsize="small")
return fig
def plot_field_cross_sections(field_data_by_design):
fig, axes = plt.subplots(
len(field_data_by_design),
1,
figsize=(12, 4.0 * len(field_data_by_design)),
constrained_layout=True,
)
axes = np.atleast_1d(axes)
for ax, (design_key, sim_data) in zip(axes, field_data_by_design.items()):
sim_data.plot_field(
field_monitor_name="field_mnt",
field_name="E",
val="abs",
ax=ax,
)
ax.set_title(f"{design_labels[design_key]} field magnitude")
ax.set_aspect("auto")
return fig