Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unified geometry interface for simulation components #139

Open
1 of 4 tasks
yaugenst opened this issue Sep 18, 2023 · 16 comments
Open
1 of 4 tasks

Unified geometry interface for simulation components #139

yaugenst opened this issue Sep 18, 2023 · 16 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@yaugenst
Copy link
Collaborator

yaugenst commented Sep 18, 2023

Is your feature request related to a problem? Please describe.
Currently, most device simulators derive their simulation properties (in particular geometries) from a patchwork of logic, e.g. from functionality contained in gdsfactory proper, from other gplugins, and self-implemented ones. This leads to a duplication of efforts and makes things harder to maintain.

Describe the solution you'd like
Ideally, there should be a single "source of truth" when it comes to simulated geometries. This could be implemented as a component base class that combines a layerstack and a component (and whatever else might be necessary that I'm not aware of currently) and provides a single interface from which all relevant attributes can be extracted easily. Developers could then implement whatever additional logic is necessary for a particular simulator on top of this interface.

I have implemented a draft of this base component in the tidy3d plugin rework (WIP) in #138 (see here). It's currently very incomplete and I've submitted it mostly because I am seeing a lot of issues crop up recently along similar lines (e.g. #119, #121, #122, #131) that could all be addressed with a common interface and I think it would be good to have a discussion.

Some considerations:

  • Immutability: A simulation component should be immutable. It is derived from a particular layerstack and device, and if any of that information changes, it should be considered a new component.
  • Owing to immutability, a component class should be hashable (implemented). This makes it easy to identify components for e.g. caching of simulation results for particular components or comparisons.
  • The base component should have a fixed interface (allow_extra=False) to provide a strong guarantee of what is and isn't provided by this class. Children should modify their own behavior as needed.
  • Ports: Since components have ports (usually), the component base should be able to provide information on port placement and sizing. I have started to implement this, and especially port sizing can (and probably should) be automated, i.e. I think one should be able to just ask the simulation component for the port sizes and it should provide them while handling spacing between ports and simulation boundaries automatically.
  • Material properties: I am undecided whether this should be done in the base component or in the derived components that different simulators use. Probably the latter because material definitions differ greatly between different simulators.
  • Visualization: Since all the geometry information is already contained in the component, there should be a way to visualize the component independent of different simulators. I have plotting implemented for the derived tidy3d component, but ideally this should live in the component base.

Long term this would enable us to add new simulators with relative ease and add new functionalities to existing ones, e.g. fabrication corner analysis is something that can simply extend the functionality of a base component (either via direct implementation or mix-ins) with little to no changes required to existing simulators (that already use the SimulationComponentBase)

If you agree that this is something that we should try to pursue, then it would be good to have a discussion on the actual interface that this component should provide. The one I've implemented is relatively bare-bones. It implements everything that's needed for tidy3d simulations, so there are very likely to be things that I've missed.

@joamatab @nikosavola @simbilod @HelgeGehring @mdecea

@yaugenst yaugenst added the enhancement New feature or request label Sep 18, 2023
@yaugenst yaugenst mentioned this issue Sep 18, 2023
@simbilod
Copy link
Collaborator

This would be beneficial to the project, although for it to be useful across simulators it cannot automate too much beyond standardizing ways of exposing (and manipulating in the case of process corners) polygon and layerstack information. Concepts such as what does a port do and how to implement simulation boundaries can be very different across simulators. Materials for sure should be implemented at the child level.

It should live inside its own gplugins submodule, and we could bring there whatever layerstack and component parsing logic from e.g. utils or the gmsh submodules that is generalizable

@yaugenst
Copy link
Collaborator Author

Yes agreed we need to find the correct layer of abstraction, which is essentially just a single way of exposing information about the layerstack and its components. This is what SimulationComponentBase is trying to achieve. Do you think there is too much going on there already?

@joamatab
Copy link
Contributor

joamatab commented Sep 18, 2023

I think is great to have, we are all reinventing the wheel for each plugin :)

thank you Yannick

@simbilod
Copy link
Collaborator

simbilod commented Sep 18, 2023

Yes agreed we need to find the correct layer of abstraction, which is essentially just a single way of exposing information about the layerstack and its components. This is what SimulationComponentBase is trying to achieve. Do you think there is too much going on there already?

I think it's a great start. Let's move it to its own submodule.

We should think about how to standardize simulation output as well. To me there seems to be two classes of output:

  • Port-related: S-parameters, IV relationships, etc.
  • Field-related: Fields, modes, charge distributions, heat profiles, etc.

It would be nice to enable simple multiphysics simulations through this unified interface. But maybe we can keep that as a next step.

@yaugenst
Copy link
Collaborator Author

Great, I renamed the SimulationComponentBase to LayeredComponentBase (no idea if that's better...) and moved it to gplugins/common/base_models. This also includes some initial simulation output models from @nikosavola, but that will need some fleshing out.

Copy link

This issue is stale because it has been inactive for 60 days. Remove stale label or comment or this will be closed in 7 days.

@joamatab
Copy link
Contributor

Why is the cladding not showing?

it's defined in the layerstack, in the same way that we define the box and the wafer

image

@yaugenst
Copy link
Collaborator Author

yaugenst commented Nov 20, 2023

@joamatab it has something to do with the cross sections. when i change the cross section of the device to "xs_rc", i get the following:

screenshot_20231119_193246

which is also not correct because the slab is missing, but now the cladding shows up 😅
@simbilod any idea what might be causing this? the polygons are pulled from gplugins.gmsh.parse_gds.cleanup_component.

@simbilod
Copy link
Collaborator

Do you guys have code I can try running to debug? I don't have experience with this plugin

@yaugenst
Copy link
Collaborator Author

right, sorry. the above plot was generated using:

import gdsfactory as gf
import matplotlib.pyplot as plt
import tidy3d as td
from gdsfactory.generic_tech import LAYER_STACK

from gplugins.tidy3d.component import Tidy3DComponent

device = gf.components.coupler_ring(cross_section="xs_rc")

# define a mapping of pdk material names to tidy3d medium objects
mapping = {
    "si": td.Medium(name="Si", permittivity=3.47**2),
    "sio2": td.Medium(name="SiO2", permittivity=1.47**2),
}

# setup the tidy3d component
c = Tidy3DComponent(
    component=device,
    layer_stack=LAYER_STACK,
    material_mapping=mapping,
    pad_xy_inner=2.0,
    pad_xy_outer=2.0,
    pad_z_inner=0,
    pad_z_outer=0,
    extend_ports=2.0,
)

# plot the component and the layerstack
fig = plt.figure(constrained_layout=True)
gs = fig.add_gridspec(ncols=2, nrows=3, width_ratios=(3, 1))
ax0 = fig.add_subplot(gs[0, 0])
ax1 = fig.add_subplot(gs[1, 0])
ax2 = fig.add_subplot(gs[2, 0])
axl = fig.add_subplot(gs[1, 1])
c.plot_slice(x="core", ax=ax0)
c.plot_slice(y="core", ax=ax1)
c.plot_slice(z="core", ax=ax2)
axl.legend(*ax0.get_legend_handles_labels(), loc="center")
axl.axis("off")
plt.show()

@simbilod
Copy link
Collaborator

For a moment I thought the issue with the slab was not doing derived layers:


device = gf.components.coupler_ring(cross_section="xs_rc")
device = LAYER_STACK.get_component_with_derived_layers(component=device)

but that also seems to miss the slab layer.

However, the polygons pulled from gplugins.gmsh.parse_gds.cleanup_component are all properly there, so it seems like the issue occurs when converting to tidy objects:

image

@simbilod
Copy link
Collaborator

simbilod commented Nov 20, 2023

geometry_layers is not getting the full list of layers present:

image

although it tries:

image

It looks like the slicing here removes one of the layer @yaugenst

return dict(tuple(layers.items())[slice(*self.slice_stack)])

@simbilod
Copy link
Collaborator

@joamatab @yaugenst it works with my latest push but I don't know what the consequence of removing this slicing are

image

@yaugenst
Copy link
Collaborator Author

Oooh thanks, good catch! Indeed, I messed up the slicing, it always removed the last layer (whatever "last" was) by default.

The idea behind having the slicing is being able to slice the stack in the component quickly (if only some layers are of interest in a simulation) instead of having to create modified stacks (which is still the more robust way to do it). Typically one would want to slice away a few of the top- and bottom-most layers. However, obviously the default slicing was wrong and additionally one needs to sort the layers by height before slicing, otherwise rib slab being sliced before cladding happens.

Fixed in 8afc65f and a6ebef8.

I'm not sure if this functionality is even useful to have in general. I personally found it convenient, but if I'm alone here we could also just remove it. Alternatively, we could go further and actually implement __getitem__() in the base component instead of having to initialize with some slice.

Copy link

This issue is stale because it has been inactive for 60 days. Remove stale label or comment or this will be closed in 7 days.

@joamatab
Copy link
Contributor

@seanlam97
@elamdf

@joamatab joamatab added the help wanted Extra attention is needed label Jan 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants