Skip to content

Conversation

@groberts-flex
Copy link
Contributor

This notebook optimizes two patch antenna structures, the first being a simple two-dimensional patch where the width and height are tuned to find the resonance. The second optimization uses a larger amount of design freedom to tune the spacings and sizes of multiple boxes to achieve dual-band operation.

All the outputs should be in the notebook from my most recent run through of the whole thing, but let me know if that isn't the case when you download it.

Copy link
Collaborator

@tylerflex tylerflex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a really awesome demo! It works super well, nice job @groberts-flex !

I'll pre-approve here, because my comments are mainly just some minor things that came up when reading through the text:

The introduction paragraph could be perhaps split up into a few separate paragraphs. Or perhaps can be smoothened a bit to really highlight what the innovation is in the notebook. For example, just rephrasing what you wrote, something like

This notebook demonstrates the use of inverse design for the optimization of antennas.

A simple rectangular patch antenna, as explored in our Antenna Characteristics notebook, is primarily defined by two parameters: its width and height. These are tuned to make the antenna resonate at a desired frequency and to match the impedance of its feed line. However, to achieve wider bandwidth or specialized features like circular polarization, designers often move beyond simple rectangular shapes. For instance, our Circularly Polarized Patch Antenna notebook details a non-rectangular radiator with parasitic strips to produce circularly polarized waves.

As antenna geometries become more intricate, the number of design parameters can increase dramatically, making traditional tuning methods inefficient. This notebook demonstrates a more powerful approach using gradient-based optimization in Tidy3D. This technique, enabled by the adjoint method and automatic differentiation (autograd), allows for the efficient and simultaneous optimization of all geometric parameters, also known as inverse design.

We will illustrate this process with two examples.
	1	First, we'll perform a straightforward optimization to find the ideal width and height of a rectangular patch for a single target frequency.
	2	Second, we will optimize a more complex antenna for dual-band operation. This design includes an optimizable inset, fins, and passive radiating elements, requiring the optimizer to simultaneously tune the dimensions and positions of all structures.
In both cases, we will hold the substrate material and thickness constant, focusing exclusively on optimizing the antenna's shape.

The two optimization geometries are shown below. Both antennas consist of a metallic patch on a substrate with a ground plane, are excited by an offset feed line, and radiate into free space. The first design is a simple rectangle defined by just two parameters, while the second, more complex design involves optimizing the dimensions and relative positions of multiple structures at once.

[1] we might want to remove setting log level error unless the warnings are unfixable?
[2] might be also useful to mention that frequencies are Hz , at least in the comment eg frequency range (Hz)

In general, there are a lot of very long functions defined up front before they ever get called. I am slightly worried it might be hard to follow for beginners. However, I'm not sure if I saw any obvious ways to improve this. this is probably one of those applications where it's hard to put everything inside of 1 single notebook without some python utility modules so I wouldn't stress about it .

Thanks!

@tylerflex
Copy link
Collaborator

Oh yea and dont forget to add this notebook to the appropriate .rst file so it gets added to the docs.

Copy link
Contributor

@yaugenst-flex yaugenst-flex Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @groberts-flex, heroic effort! I agree it looks great overall, so I'll also mostly resort to nit-picking:

  1. The introduction is a ~20 line paragraph. Splitting this into a couple of shorter paragraphs would make this a lot easier to digest.

  2. The leading image is cut off for me on the right (see screenshot, and notice the scroll bar too):

    Image

    Let's try to make these illustrations fit?

  3. In cell [2], sub_z is assigned twice to different values.

  4. The first optimization loop prints a lot of information at every iteration. I guess this is a matter of taste, but I find it quite noisy and it makes it a bit harder to scroll through the notebook. I feel like trimming this down would help. For example, gradients, updates, and params are somewhat redundant/interchangeable no? And/or reducing the print cadence (also for the second optimization). Basically, the longer these logs are, the more these will eclipse the actual figures and overall flow of the notebook.

  5. Also not sure if this is possible, but can we suppress the validation logs? They're pretty distracting in that loop.

  6. I noticed a couple of typos ("optimziation", "inital"), but i think these should be caught by the spellcheck. On that note, the notebook needs a ruff pass.

@groberts-flex
Copy link
Contributor Author

Thank you @tylerflex and @yaugenst-flex for the really helpful comments! I tried to get them implemented and below are a few notes responses to each.

Tyler's comments:
I really liked how your rewritten intro read and essentially dropped that in with a few small changes.

  1. I was able to fix one of the warnings that is coming up but the other warning that pops up is the substrate structure being half a wavelength from the PML (and also warnings about RF usage being billed differently in the future). I went the route of the other patch antenna notebook that also has a similar substrate setup where I let those warnings come out before the optimization so that users can be aware of them, but then turned them off for the optimization loop so they don't crowd the output a bunch.
  2. good point on the frequencies, updated!

Yannick's comments:

  1. good point, updated according to Tyler's suggestion and think it's more digestible now!
  2. thanks for noticing this - interestingly it doesn't cut off when I have it in my browser, but shrunk the figure sizes a bit so it also doesn't require a scroll in the GitHub preview to be safe
  3. good catch
  4. trimmed things down a bit - realized some of the extra info was just more helpful for me when developing and agree it's much cleaner to have it just be the parameters. I also reduced the printing cadence in both optimizations.
  5. these should suppress now on re-run which I'll do before publishing
  6. did the ruff pass, but how do I run the spell checker?

Copy link
Contributor

@yuanshen-flexcompute yuanshen-flexcompute left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@groberts-flex This is a tremendous effort and an exciting showcase of our new functionality! Great job on developing this feature.

That said, I do have some big picture concerns about its presentation. Who is the target audience for this notebook?

  • Given its length and complexity, beginner and even intermediate users of Tidy3D will be intimidated and likely not finish reading the notebook. Advanced users of Tidy3D familiar with existing adjoint optimization features might be able to digest it, but they are a minority and probably not the target audience.
  • If we are trying to attract new RF users, we do not want to present them the impression that our adjoint optimization is difficult to use and requires expert-level coding skills/API knowledge. Unlike the photonics field, it is not as common for RF users to have a PhD degree.

Some other concerns:

  • What is the FC cost of running each optimization? It would be good to provide feedback with every step. Users running this notebook on their own dime will probably care it is too large.

With all that said, I have a few suggestions:

  • Would it be possible to sequester the non-essential code (from a pedagogical perspective) into a separate .py file in the misc folder that is imported at the beginning? I'm referring to methods like plot_antenna_comparison, plot_antenna_evalution etc., that are not critical to understanding the adjoint workflow. This will reduce the amount of code that the reader has to parse and avoid confusion about the main learning points.
  • Would it be possible to show the FC cost of each optimization iteration?
  • There are a lot of wrapper functions in the notebook that call other wrapper functions. For example, evaluate_single_antenna calls evaluate_antenna calls create_modeler and params_to_box_single_patch and create_sim_with_patches and so on. This functions are also defined across disparate cells in the notebook. This can obfuscate the workflow and make it even more difficult for the reader to understand the "sequence of events". Would it be possible to reduce the number of wrapper functions, or if that is not possible, present the entire workflow in a logical sequential fashion? (Maybe even include a visual aid, like a flowchart?)
  • Instead of using a dense grid enforced by the MeshOverrideStructure, have you experimented with using LayerRefinementSpec instead? (For example, see the Edge Feed Patch Antenna benchmark notebook.) I wonder if this can further reduce run time and cost while offering similar performance.
  • Finally, have you considered splitting the notebook into two notebooks? The first one could cover the basic patch antenna W and H optimization, and serve to introduce the adjoint optimization workflow. The second notebook could then extend that workflow to the more complicated design. Having two shorter notebooks could improve approachability.

All in all, I think this is a great notebook with exciting content, but just needs to be packaged in a more approachable fashion. :)

@groberts-flex
Copy link
Contributor Author

Thanks @yuanshen-flexcompute for the really useful feedback. I think it's a good point to split the notebook into two and I've included the first of two in this update. If it looks good, I'll build the second one similarly and simplify the functions and workflow as much as possible there. I think after the first one it'll be easier for someone to get started on the second and hopefully will be less intimidating for users. That notebook file is now in RFAutograd1RectangularPatchAntennaSplit1.ipynb. Once everything looks good to go I'll remove the "Split1" and just make it "1" and the second split "2". Some point-by-point responses to your questions/feedback:

  • for the audience, I do think we want to make it as inviting as possible for people who are familiar with adjoint but especially potential new users to adjoint who do more traditional RF design. I think the splitting and simplification of the notebook has helped with that presentation but let me know if it still seems like too high of a barrier to entry. If so, @athielens-fc had an interesting idea to try and make some video content to go along with this for RF users who may be interested in adjoint but haven't really explored it in the photonic case.

  • for FC cost, running end to end it probably lands around 16 FC or so. I've put into one of the functions a log of how much each individual simulation (and also adjoint iteration) takes and some extra explanation on it. Hopefully this helps people gauge if they want to re-run it or not or if they are considering how expensive this optimization might be in general.

  • for the plotting code, I'm not sure we can put those functions into a separate file since then the notebook would not be able to run self-contained and would require the user to download that file as well. I think it would be useful to have this more hidden, but I'm not sure of the right solution for this. One option would be to just reduce the amount of plotting that gets done so that the very core functionality is demonstrated. I'm thinking I could remove the plotting of the S11 and directivity over the course of the optimization.

  • I tried to remove as many wrapped functions as possible and reduce the amount of arguments that are being passed around. This was more helpful when I had the second optimization that was getting run in the notebook where I wanted to re-use code. I also added a flowchart to show the core gradient computation code with the most important functions for it.

  • I tried things with LayerRefinementSpec and it does reduce the simulation time by about a factor of 2. However, I do notice a pretty significant seeming resonance shift when I switch between the LayerRefinementSpec and the fixed MeshOverrideStructure. Has there been some benchmarking done on the convergence/accuracy when using LayerRefinementSpec versus a fixed, fine mesh?

@yuanshen-flexcompute
Copy link
Contributor

@groberts-flex Thanks for the edits! Here are my comments for the latest version:

  • Preamble: You did link the Antenna Characteristics notebook (title should be Introduction to Antenna Simulation), but I think we should explicit recommend the reader to work through that notebook first, and that this notebook presumes knowledge of the basic RF modeling workflow.
  • Cell [1] mentions set logging level, but no logging level is set
  • Cell [2] gives execution error since freqs is never defined
  • What about putting the non-essential plotting and evaluation functions into a separate .py module and importing it in this notebook? This should be ok as long as the .py file is included in /misc/import_file_mapping.json. @tomflexcompute Would that work for user-defined python modules?
  • If the plotting and evaluation functions cannot be separate from the notebook, it would be helpful to explain to the user which ones are less important to understanding the overall workflow, so that he/she can just skim over it.
  • The flow-chart is a very useful addition, although the image can be larger for better legibility. The actual flow is also not 100% clear to me based on the chart - in particular, the autograd portion with a two-headed arrow can be confusing.
  • The cost of this optimization is concerning. 16 FC seems too high to me for a simple problem such as this, and might deter users from running this tutorial. (Trial users get only 10 FC if I remember correctly.) Are there places where we can reduce the cost? How does cost scale with the various optimization parameters? I think the user would also appreciate a discussion of how cost relates to various optimization settings.
  • There are a lot of RuntimeWarnings during the optimization process. Where are they coming from, and is it possible to avoid them? If not, we should at least make a note of it to the user so that they are not overly concerned.
  • It is surprising that using LayerRefinementSpec should cause the result to change significantly. How are you implementing it? There is an available antenna benchmark using LayerRefinementSpec and convergence test, see this notebook

@groberts-flex
Copy link
Contributor Author

Thanks @yuanshen-flexcompute for the feedback on the new version!

  1. updated preamble to strongly recommend they look at other notebook first and fixed the name of it in the link
  2. good catch, removed logging level part of comment
  3. good catch, fixed the missing freqs variable
  4. I'm definitely open to putting the plotting functions into a separate .py file. I think the concern I had though was if a user downloads the notebook to run from the tidy3d site. They won't have the .py file in that download I would assume?
  5. I marked the plotting/eval functions section with a note that tells the reader they don't really need to look through the functions for understanding the notebook and that they are mostly for visualization purposes.
  6. Thanks, I increased the size and updated the flowchart a bit. The double arrow was meant to show the connection between the gradient and input parameters that was formed via autograd. I changed this around to hopefully be more clear and show the loop of computing the gradient and updating the parameters.
  7. See below, but I was able to reduce the simulation cost quite a bit with LayerRefinementSpec and now the notebook is about 3.5 FC to run. The iteration cost doesn't scale with the number of optimization parameters which is the advantage of the adjoint method. So while this is a simple demonstration, the cost isn't higher to optimize a polyslab antenna with a more elaborate shape, provided the number of iterations to reach convergence isn't much larger in that case.
  8. The runtime warnings were coming from something that had been merged recently into develop. I merged a fix for this, so they are gone now.
  9. Thanks for sending the additional notebook. I played around more with the settings for the LayerRefinementSpec and found a good configuration that achieved an accurate simulation result and reduced the simulation cost by about 5X!

@yuanshen-flexcompute
Copy link
Contributor

@groberts-flex Awesome updates! It's great that the cost of the optimization has gone down so significantly. I am currently trying to re-run your latest update, but on cell 11, I get the error: NameError: name 'mesh_override_vertical_padding' is not defined.

@groberts-flex
Copy link
Contributor Author

groberts-flex commented Oct 15, 2025

@groberts-flex Awesome updates! It's great that the cost of the optimization has gone down so significantly. I am currently trying to re-run your latest update, but on cell 11, I get the error: NameError: name 'mesh_override_vertical_padding' is not defined.

@yuanshen-flexcompute, thanks for running through the notebook. Sorry about the error, I overpruned some code in there. I've put that variable back in and pushed the notebook up again, but haven't had time to rerun it yet myself to make sure there are no other errors. I'll kick off a re-run tonight but feel free to give it another try if you like!

@tomflexcompute
Copy link
Contributor

@groberts-flex please edit the corresponding rst file (docs/features/autograd.rst I assume?) and notebook metadata (following instructions here).

Could you prepare a thumbnail image for the notebook? @yuanshen-flexcompute and I can prepare one for you as well if needed.

Copy link
Contributor

@yuanshen-flexcompute yuanshen-flexcompute left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Part 1 looks good to me. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants