gplugins icon indicating copy to clipboard operation
gplugins copied to clipboard

Unified geometry interface for simulation components

Open yaugenst opened this issue 2 years ago • 16 comments

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.

  • [x] tidy3d https://github.com/gdsfactory/gplugins/pull/239
  • [ ] meep
  • [ ] Palace
  • [ ] lumerical

@joamatab @nikosavola @simbilod @HelgeGehring @mdecea

yaugenst avatar Sep 18 '23 16:09 yaugenst

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

simbilod avatar Sep 18 '23 17:09 simbilod

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?

yaugenst avatar Sep 18 '23 17:09 yaugenst

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

thank you Yannick

joamatab avatar Sep 18 '23 18:09 joamatab

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.

simbilod avatar Sep 18 '23 19:09 simbilod

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.

yaugenst avatar Sep 19 '23 03:09 yaugenst

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.

github-actions[bot] avatar Nov 18 '23 12:11 github-actions[bot]

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

joamatab avatar Nov 19 '23 17:11 joamatab

@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 :sweat_smile: @simbilod any idea what might be causing this? the polygons are pulled from gplugins.gmsh.parse_gds.cleanup_component.

yaugenst avatar Nov 20 '23 03:11 yaugenst

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

simbilod avatar Nov 20 '23 03:11 simbilod

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()

yaugenst avatar Nov 20 '23 03:11 yaugenst

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 avatar Nov 20 '23 04:11 simbilod

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

https://github.com/gdsfactory/gplugins/blob/281845d4a9e3ed323f96a911dfc1ef69a44a8d9c/gplugins/common/base_models/component.py#L105

simbilod avatar Nov 20 '23 05:11 simbilod

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

image

simbilod avatar Nov 20 '23 05:11 simbilod

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.

yaugenst avatar Nov 20 '23 06:11 yaugenst

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.

github-actions[bot] avatar Jan 28 '24 12:01 github-actions[bot]

@seanlam97 @elamdf

joamatab avatar Jan 29 '24 00:01 joamatab