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

Move all non-plugin directories into 'common' module #148

Merged
merged 7 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs/api_design.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ FDTD Simulation

.. rubric:: Sparameter utils

.. currentmodule:: gplugins.utils.plot
.. currentmodule:: gplugins.common.utils.plot

.. autosummary::
:toctree: _autosummary/
Expand All @@ -104,19 +104,19 @@ FDTD Simulation

.. rubric:: common FDTD functions

.. currentmodule:: gplugins.utils.get_effective_indices
.. currentmodule:: gplugins.common.utils.get_effective_indices

.. autosummary::
:toctree: _autosummary/

get_effective_indices

.. currentmodule:: gplugins.utils.port_symmetries
.. currentmodule:: gplugins.common.utils.port_symmetries

.. autosummary::
:toctree: _autosummary/

.. currentmodule:: gplugins.utils.convert_sparameters
.. currentmodule:: gplugins.common.utils.convert_sparameters

.. autosummary::
:toctree: _autosummary/
Expand Down
2 changes: 1 addition & 1 deletion docs/notebooks/palace_01_electrostatic.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@
from gdsfactory.technology.layer_stack import LayerLevel
from IPython.display import display

from gplugins.common.types import RFMaterialSpec
from gplugins.palace import run_capacitive_simulation_palace
from gplugins.typings.materials import RFMaterialSpec

gf.config.rich_output()
PDK = get_generic_pdk()
Expand Down
2 changes: 1 addition & 1 deletion docs/notebooks/palace_02_fullwave.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@
from IPython.display import display
from matplotlib import pyplot as plt

from gplugins.common.types import RFMaterialSpec
from gplugins.palace import run_scattering_simulation_palace
from gplugins.typings.materials import RFMaterialSpec

gf.config.rich_output()
PDK = get_generic_pdk()
Expand Down
2 changes: 1 addition & 1 deletion docs/notebooks/sax_01_sax.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

import gplugins.sax as gs
import gplugins.tidy3d as gt
from gplugins.config import PATH
from gplugins.common.config import PATH

gf.config.rich_output()
PDK = get_generic_pdk()
Expand Down
2 changes: 1 addition & 1 deletion docs/notebooks/tidy3d_00_tidy3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

import gplugins.tidy3d as gt
from gplugins import utils
from gplugins.config import PATH
from gplugins.common.config import PATH

# %%
print(gt.materials.MaterialSpecTidy3d)
Expand Down
2 changes: 1 addition & 1 deletion docs/notebooks/workflow_1_mzi.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def neff_w(w):

import gplugins as sim
import gplugins.tidy3d as gt
from gplugins.config import PATH
from gplugins.common.config import PATH

c = pdk.mmi1x2()
c.plot()
Expand Down
2 changes: 1 addition & 1 deletion docs/notebooks/workflow_3_cascaded_mzi.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import tidy3d as td

import gplugins.tidy3d as gt
from gplugins.config import PATH
from gplugins.common.config import PATH

# %% [markdown]
# We start by loading the desired PDK and setting the main geometry and filter parameters, such as DC gap and central wavelength.
Expand Down
4 changes: 2 additions & 2 deletions gplugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

__version__ = "0.6.0"

from gplugins.utils import plot, port_symmetries
from gplugins.utils.get_effective_indices import get_effective_indices
from gplugins.common.utils import plot, port_symmetries
from gplugins.common.utils.get_effective_indices import get_effective_indices

__all__ = ["plot", "get_effective_indices", "port_symmetries"]
File renamed without changes.
File renamed without changes.
225 changes: 225 additions & 0 deletions gplugins/common/base_models/component.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
from functools import cached_property
from hashlib import md5

import gdsfactory as gf
import numpy as np
from gdsfactory.component import Component
from gdsfactory.technology import LayerLevel, LayerStack
from pydantic import (
BaseModel,
ConfigDict,
NonNegativeFloat,
computed_field,
)
from shapely import MultiPolygon, Polygon

from gplugins.gmsh.parse_gds import cleanup_component

from ..types import AnyShapelyPolygon, GFComponent


class LayeredComponentBase(BaseModel):
model_config = ConfigDict(
frozen=True,
extra="forbid",
arbitrary_types_allowed=True,
allow_inf_nan=False,
validate_return=True,
)

component: GFComponent
layerstack: LayerStack
extend_ports: NonNegativeFloat = 0.0
port_offset: float = 0.0
pad_xy_inner: float = 0.0
pad_xy_outer: NonNegativeFloat = 0.0
pad_z_inner: float = 0.0
pad_z_outer: NonNegativeFloat = 0.0
wafer_layer: tuple[int, int] = (99999, 0)
slice_stack: tuple[int, int] = (0, -1)

def __hash__(self):
if not hasattr(self, "_hash"):
dump = str.encode(self.model_dump_json())
self._hash = int(md5(dump).hexdigest()[:15], 16)
return self._hash

@property
def pad_xy(self) -> float:
return self.pad_xy_inner + self.pad_xy_outer

@property
def pad_z(self) -> float:
return self.pad_z_inner + self.pad_z_outer

@cached_property
def gds_component(self) -> GFComponent:
c = Component(name=f"sim_component_{self.component.name}")
c << gf.components.extend_ports(
self.component, length=self.extend_ports + self.pad_xy
)
c << gf.components.bbox(
self._gds_bbox,
layer=self.wafer_layer,
top=self.pad_xy_outer,
bottom=self.pad_xy_outer,
left=self.pad_xy_outer,
right=self.pad_xy_outer,
)
c.add_ports(self.gds_ports)
c.copy_child_info(self.component)
return c

@cached_property
def _gds_bbox(self) -> tuple[tuple[float, float], tuple[float, float]]:
c = gf.components.extend_ports(
self.component, length=self.extend_ports + self.pad_xy_inner
).ref()
unchanged = np.isclose(np.abs(np.round(c.bbox - self.component.bbox, 3)), 0)
bbox = c.bbox + unchanged * np.array([[-1, -1], [1, 1]]) * self.pad_xy_inner
return tuple(map(tuple, bbox))

@cached_property
def gds_ports(self) -> dict[str, gf.Port]:
return {
n: p.move_polar_copy(self.extend_ports - self.port_offset, p.orientation)
for n, p in self.component.ports.items()
}

@computed_field
@cached_property
def polygons(self) -> dict[str, AnyShapelyPolygon]:
return cleanup_component(
self.gds_component, self.layerstack, round_tol=3, simplify_tol=1e-3
)

@cached_property
def geometry_layers(self) -> dict[str, LayerLevel]:
layers = {
k: v
for k, v in self.layerstack.layers.items()
if not self.polygons[k].is_empty
}
return dict(tuple(layers.items())[slice(*self.slice_stack)])

@property
def xmin(self) -> float:
return self._gds_bbox[0][0]

@property
def xmax(self) -> float:
return self._gds_bbox[1][0]

@property
def ymin(self) -> float:
return self._gds_bbox[0][1]

@property
def ymax(self) -> float:
return self._gds_bbox[1][1]

@cached_property
def zmin(self) -> float:
return (
min(
min(layer.zmin, layer.zmin + layer.thickness)
for layer in self.geometry_layers.values()
)
- self.pad_z_inner
)

@cached_property
def zmax(self) -> float:
return (
max(
max(layer.zmin, layer.zmin + layer.thickness)
for layer in self.geometry_layers.values()
)
+ self.pad_z_inner
)

@property
def bbox(self) -> tuple[tuple[float, float, float], tuple[float, float, float]]:
return (*self._gds_bbox[0], self.zmin), (*self._gds_bbox[1], self.zmax)

@property
def center(self) -> tuple[float, float, float]:
return tuple(np.mean(self.bbox, axis=0))

@property
def size(self) -> tuple[float, float, float]:
return tuple(np.squeeze(np.diff(self.bbox, axis=0)))

@cached_property
def bottom_layer(self) -> str:
return min(
self.geometry_layers.items(),
key=lambda item: min([item[1].zmin, item[1].zmin + item[1].thickness]),
)[0]

@cached_property
def top_layer(self) -> str:
return max(
self.geometry_layers.items(),
key=lambda item: max([item[1].zmin, item[1].zmin + item[1].thickness]),
)[0]

@cached_property
def device_layers(self) -> tuple[str, ...]:
return tuple(
k
for k, v in self.layerstack.layers.items()
if v.layer in self.component.layers
)

@cached_property
def port_centers(self) -> tuple[tuple[float, float, float], ...]:
return tuple(self.get_port_center(p) for p in self.gds_ports.values())

@cached_property
def port_sizes(self):
# TODO calculate maximum port sizes from neighbors
for name, port in self.gds_ports.items():
print(name, self.port_center(port))

def get_port_center(self, port: gf.Port) -> tuple[float, float, float]:
layer_czs = np.array(tuple(self.layer_centers.values()))
return (
*port.center,
np.mean(
[
layer_czs[idx, 2]
for idx, layer in enumerate(self.geometry_layers.values())
if layer.layer == port.layer
]
),
)

def get_layer_bbox(
self, layername: str
) -> tuple[tuple[float, float, float], tuple[float, float, float]]:
layer = self.layerstack[layername]
bounds_xy = self.polygons[layername].bounds
zmin, zmax = sorted([layer.zmin, layer.zmin + layer.thickness])

if layername == self.bottom_layer:
zmin -= self.pad_z
if layername == self.top_layer:
zmax += self.pad_z

return (*bounds_xy[:2], zmin), (*bounds_xy[2:], zmax)

def get_layer_center(self, layername: str) -> tuple[float, float, float]:
bbox = self.get_layer_bbox(layername)
return tuple(np.mean(bbox, axis=0))

def get_vertices(self, layer_name: str, buffer: float = 0.0):
poly = self.polygons[layer_name].buffer(buffer, join_style="mitre")
match poly:
case MultiPolygon():
verts = tuple(tuple(p.exterior.coords) for p in poly.geoms)
case Polygon():
verts = (tuple(poly.exterior.coords),)
case _:
raise TypeError(f"Invalid polygon type: {type(poly)}")
return verts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from pydantic import BaseModel, ConfigDict

from .materials import CapacitanceDict
from ..types import CapacitanceDict


class ElectrostaticResults(BaseModel):
Expand Down
2 changes: 1 addition & 1 deletion gplugins/config.py → gplugins/common/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
home_config = home / ".config" / "gplugins.yml"
config_dir = home / ".config"
config_dir.mkdir(exist_ok=True)
module_path = pathlib.Path(__file__).parent.absolute()
module_path = pathlib.Path(__file__).parents[1].absolute()
repo_path = module_path.parent


Expand Down
15 changes: 15 additions & 0 deletions gplugins/common/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from typing import Annotated

from gdsfactory import Component
from pydantic.functional_serializers import PlainSerializer
from shapely import GeometryCollection, MultiPolygon, Polygon

RFMaterialSpec = dict[str, dict[str, float | int]]
CapacitanceDict = dict[tuple[str, str], float]
AnyShapelyPolygon = Annotated[
GeometryCollection | MultiPolygon | Polygon,
PlainSerializer(lambda x: x.wkb_hex, when_used="json"),
]
GFComponent = Annotated[
Component, PlainSerializer(lambda x: x.to_dict(), when_used="json")
]
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def add_simulation_markers(
:include-source:

import gdsfactory as gf
from gplugins.utils.add_simulation_markers import add_simulation_markers
from gplugins.common.utils.add_simulation_markers import add_simulation_markers

c = gf.components.bend_circular()
c = add_simulation_markers(c)
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
import gdsfactory as gf
from gdsfactory.typings import ComponentSpec

from gplugins.common.base_models.simulation import ElectrostaticResults
from gplugins.elmer.get_capacitance import run_capacitive_simulation_elmer
from gplugins.palace.get_capacitance import (
run_capacitive_simulation_palace,
)
from gplugins.typings.simulation import ElectrostaticResults


def get_capacitance_path() -> Path:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from gdsfactory.pdk import get_sparameters_path
from gdsfactory.typings import ComponentSpec

from gplugins.common.base_models.simulation import DrivenFullWaveResults
from gplugins.palace.get_scattering import run_scattering_simulation_palace
from gplugins.typings.simulation import DrivenFullWaveResults


def get_scattering(
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from gdsfactory.components import straight_heater_metal
from gdsfactory.generic_tech import LAYER_STACK

from gplugins.utils.get_component_with_new_port_layers import (
from gplugins.common.utils.get_component_with_new_port_layers import (
get_component_layer_stack,
get_component_with_new_port_layers,
)
Expand Down
Loading