Archived seminar material. These saved outputs were produced with Tidy3D 2.9.1
With our simulation setup in place, we now turn to optimization. Our goal is to find a set of grating parameters that maximizes the coupling efficiency. Since each simulation is computationally expensive, we will use Bayesian optimization. This technique is ideal for optimizing “black-box” functions that are costly to evaluate.
Why Bayesian Optimization?
Exhaustive searches would require thousands of simulations. Bayesian optimization instead builds a probabilistic surrogate of the objective, balancing exploration of uncertain regions with exploitation of promising designs to converge in far fewer solver calls. It intelligently explores the parameter space to find the optimal design with a minimal number of simulations. Bayesian optimization works best when the design space has only a handful of effective degrees of freedom; beyond roughly five independent variables the surrogate becomes harder to learn, so we reserve higher-dimensional searches for gradient-based methods discussed later in the series.
import matplotlib.pyplot as pltimport numpy as npimport tidy3d as tdfrom bayes_opt import BayesianOptimizationfrom setup import ( center_wavelength, get_mode_monitor_power, make_simulation, max_gap_si, max_gap_sin, max_width_si, max_width_sin, min_gap_si, min_gap_sin, min_width_si, min_width_sin, num_elements,)from setup import ( first_gap_si as default_first_gap_si,)from tidy3d import web
The Evaluation Function
The optimizer queries this function with a candidate set of grating parameters. We construct the simulation, run it in the cloud, and return the coupling efficiency from the mode monitor.
We configure the optimizer with sensible defaults and practical bounds: - parameter_bounds (the pbounds argument) defines the design window we explore. - init_points sets how many random samples to collect before modeling. - n_iter controls the number of guided optimization iterations.
Framing the Problem: A 5-Parameter Global Search
Rather than tune every tooth individually (30 variables per layer), we search a five-dimensional space of uniform widths, gaps, and inter-layer offset. This captures the dominant physics, keeps simulations fast, and yields a design that later gradient-based passes can refine.
We extract the optimizer history, track the best observed loss, and visualize how the search converges toward high-efficiency gratings.
best = optimizer.maxresults = optimizer.resiterations = np.arange(1, len(results) +1)targets = np.asarray([res["target"] for res in results], dtype=float)targets = np.maximum(targets, 1e-12)coupling_loss_db =-10* np.log10(targets)best_loss = np.minimum.accumulate(coupling_loss_db)best_loss_db =-10* np.log10(max(best["target"], 1e-12))print("Optimization complete.")print(f"Best parameters: {best['params']}")print(f"Best objective (power): {best['target']}")print(f"Best objective (dB): {best_loss_db:.2f}")
Optimization complete.
Best parameters: {'first_gap_si': np.float64(-0.6933388041768698), 'gap_si': np.float64(0.7992416233438039), 'gap_sin': np.float64(0.5135103145142313), 'width_si': np.float64(0.3983180007432449), 'width_sin': np.float64(0.5781958117277934)}
Best objective (power): 0.3425821844561507
Best objective (dB): 4.65
Interpreting the Optimization Progress
The scatter points show every simulation the optimizer evaluated, while the red curve tracks the best coupling loss found so far. Early iterations explore widely; later ones cluster near promising regions as the surrogate model focuses on exploitation.
fig, ax = plt.subplots(figsize=(6, 4))ax.scatter(iterations, coupling_loss_db, label="Samples")ax.plot(iterations, best_loss, color="red", label="Best so far")ax.set_xlabel("Iteration")ax.set_ylabel("Coupling loss (dB)")ax.set_title("Bayesian optimization progress")ax.legend()plt.grid(True, alpha=0.3)plt.show()
Visualizing the Optimized Design
We reconstruct the best-performing structure, inspect its geometry, and analyze the spectral response to confirm the optimizer’s progress.
best_params = {name: float(value) for name, value in best["params"].items()}best_widths_si = np.full(num_elements, best_params["width_si"])best_gaps_si = np.full(num_elements, best_params["gap_si"])best_widths_sin = np.full(num_elements, best_params["width_sin"])best_gaps_sin = np.full(num_elements, best_params["gap_sin"])best_first_gap_si = best_params["first_gap_si"]
best_sim = make_simulation( best_widths_si, best_gaps_si, best_widths_sin, best_gaps_sin, first_gap_si=best_first_gap_si, include_field_monitor=True,)ax = best_sim.plot(y=0)ax.set_title("Cross-section of the optimized grating (y=0)")plt.show()
ax = best_data.plot_field("field_monitor", "Ey", "abs^2")ax.set_title("Field intensity |Ey|^2 for the optimized design")plt.show()
The optimized geometry increases overlap between the free-space beam and the guided mode, yielding a stronger steady-state field inside the silicon nitride layer. In the next notebook we leverage this design as the starting point for gradient-based refinement.
Exporting the Best Design
We serialize the best uniform grating parameters so the adjoint notebook can continue from this design without rerunning the Bayesian search.
import jsonfrom pathlib import Pathexport_path = Path("./results/gc_bayes_opt_best.json")export_path.parent.mkdir(parents=True, exist_ok=True)export_payload = {"width_si": best_params["width_si"],"gap_si": best_params["gap_si"],"width_sin": best_params["width_sin"],"gap_sin": best_params["gap_sin"],"first_gap_si": best_params["first_gap_si"],"target_power": float(best["target"]),"coupling_loss_db": float(best_loss_db),}with export_path.open("w", encoding="utf-8") as f: json.dump(export_payload, f, indent=2)print(f"Saved best design to {export_path.resolve()}")
Saved best design to /home/yannick/flexcompute/worktrees/seminar_notebooks/docs/notebooks/2025-10-09-invdes-seminar/results/gc_bayes_opt_best.json
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.