gdsfactory / gplugins

gdsfactory plugins
https://gdsfactory.github.io/gplugins/
MIT License
34 stars 28 forks source link

Unified geometry interface for simulation components #139

Open yaugenst opened 11 months ago

yaugenst commented 11 months ago

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:

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

simbilod commented 11 months ago

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 commented 11 months ago

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 commented 11 months ago

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

thank you Yannick

simbilod commented 11 months ago

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:

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

yaugenst commented 11 months ago

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.

github-actions[bot] commented 9 months ago

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 commented 9 months ago

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 commented 9 months ago

@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.

simbilod commented 9 months ago

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

yaugenst commented 9 months ago

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 commented 9 months ago

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 commented 9 months ago

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 commented 9 months ago

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

image

yaugenst commented 9 months ago

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.

github-actions[bot] commented 6 months ago

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 commented 6 months ago

@seanlam97 @elamdf