Skip to content
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
10 changes: 10 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ repos:
- id: ruff-format
files: ^gplugins/(femwell|gmsh|meow|sax|tidy3d|klayout|vlsir)/

- repo: https://github.com/pre-commit/mirrors-mypy
rev: "v1.15.0"
hooks:
- id: mypy
args: [--ignore-missing-imports, --strict, --config-file=pyproject.toml]
additional_dependencies:
- gdsfactory
- pytest
files: ^gplugins/(femwell|gmsh|meow|sax|tidy3d|klayout|vlsir)/

# - repo: https://github.com/shellcheck-py/shellcheck-py
# rev: v0.9.0.5
# hooks:
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ venv:

install:
uv venv --python 3.11
uv pip install -e .[dev,docs,devsim,femwell,gmsh,klayout,meow,sax,schematic,tidy3d,vlsir]
uv pip install -e .[dev,docs,femwell,gmsh,meow,sax,tidy3d,klayout,vlsir]
uv run pre-commit install

dev: test-data gmsh elmer install
Expand Down
14 changes: 6 additions & 8 deletions gplugins/common/utils/get_component_with_net_layers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import copy

import gdsfactory as gf
import klayout.db as kdb
from gdsfactory import Component
from gdsfactory.technology import LayerStack, LogicalLayer

Expand Down Expand Up @@ -35,8 +36,8 @@ def get_component_layer_stack(


def get_component_with_net_layers(
component,
layer_stack,
component: Component,
layer_stack: LayerStack,
port_names: list[str],
delimiter: str = "#",
new_layers_init: tuple[int, int] = (10010, 0),
Expand Down Expand Up @@ -74,7 +75,9 @@ def get_component_with_net_layers(
net_component = net_component.remove_layers(layers=(port.layer,))
for polygon in polygons:
# If polygon belongs to port, create a unique new layer, and add the polygon to it
if polygon.sized(3 * gf.kcl.dbu).inside(port.center):
if polygon.sized(int(3 * gf.kcl.dbu)).inside(
kdb.Point(*port.to_itype().center)
):
# if gdstk.inside(
# [port.center],
# gdstk.offset(gdstk.Polygon(polygon), gf.get_active_pdk().grid_size),
Expand Down Expand Up @@ -111,8 +114,3 @@ def get_component_with_net_layers(

net_component.name = f"{component.name}_net_layers"
return net_component


if __name__ == "__main__":
c = get_component_with_net_layers()
c.show()
25 changes: 14 additions & 11 deletions gplugins/common/utils/get_effective_indices.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

from __future__ import annotations

from typing import Literal
from typing import Any, Literal, cast

import numpy as np
import numpy.typing as npt
from scipy.optimize import fsolve


Expand All @@ -19,9 +20,9 @@ def get_effective_indices(
"""Returns the effective refractive indices for a 1D mode.

Args:
epsilon_core: Relative permittivity of the film.
epsilon_substrate: Relative permittivity of the substrate.
epsilon_cladding: Relative permittivity of the cladding.
core_material: Refractive index of the core material.
nsubstrate: Refractive index of the substrate.
clad_materialding: Refractive index of the cladding.
thickness: Thickness of the film in um.
wavelength: Wavelength in um.
polarization: Either "te" or "tm".
Expand Down Expand Up @@ -66,18 +67,20 @@ def get_effective_indices(

k_0 = 2 * np.pi / wavelength

def k_f(e_eff):
def k_f(e_eff: npt.NDArray[np.floating[Any]]) -> npt.NDArray[np.floating[Any]]:
return k_0 * np.sqrt(epsilon_core - e_eff) / (epsilon_core if tm else 1)

def k_s(e_eff):
def k_s(e_eff: npt.NDArray[np.floating[Any]]) -> npt.NDArray[np.floating[Any]]:
return (
k_0 * np.sqrt(e_eff - epsilon_substrate) / (epsilon_substrate if tm else 1)
)

def k_c(e_eff):
def k_c(e_eff: npt.NDArray[np.floating[Any]]) -> npt.NDArray[np.floating[Any]]:
return k_0 * np.sqrt(e_eff - epsilon_cladding) / (epsilon_cladding if tm else 1)

def objective(e_eff):
def objective(
e_eff: npt.NDArray[np.floating[Any]],
) -> npt.NDArray[np.floating[Any]]:
return 1 / np.tan(k_f(e_eff) * thickness) - (
k_f(e_eff) ** 2 - k_s(e_eff) * k_c(e_eff)
) / (k_f(e_eff) * (k_s(e_eff) + k_c(e_eff)))
Expand All @@ -92,14 +95,14 @@ def objective(e_eff):
return []

# and then use fsolve to get exact indices
indices_temp = fsolve(objective, indices_temp)
indices_temp = cast(npt.NDArray[np.floating[Any]], fsolve(objective, indices_temp))

indices = []
indices: list[float] = []
for index in indices_temp:
if not any(np.isclose(index, i, atol=1e-5) for i in indices):
indices.append(index)

return np.sqrt(indices).tolist()
return cast(list[float], np.sqrt(indices).tolist())


def test_effective_index() -> None:
Expand Down
13 changes: 7 additions & 6 deletions gplugins/common/utils/parse_layer_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def list_unique_layer_stack_z(
def map_unique_layer_stack_z(
layer_stack: LayerStack,
include_zmax: bool = True,
):
) -> dict[str, set[float]]:
"""Map unique LayerStack z coordinates to various layers.

Args:
Expand Down Expand Up @@ -57,7 +57,7 @@ def map_unique_layer_stack_z(
def get_layer_overlaps_z(
layer_stack: LayerStack,
include_zmax: bool = True,
):
) -> dict[float, set[str]]:
"""Maps layers to unique LayerStack z coordinates.

Args:
Expand All @@ -67,7 +67,7 @@ def get_layer_overlaps_z(
"""
z_grid = list_unique_layer_stack_z(layer_stack)
unique_z_dict = map_unique_layer_stack_z(layer_stack, include_zmax)
intersection_z_dict = {}
intersection_z_dict: dict[float, set[str]] = {}
for z in z_grid:
current_layers = {
layername for layername, layer_zs in unique_z_dict.items() if z in layer_zs
Expand All @@ -77,11 +77,12 @@ def get_layer_overlaps_z(
return intersection_z_dict


def get_layers_at_z(layer_stack: LayerStack, z: float):
def get_layers_at_z(layer_stack: LayerStack, z: float) -> list[str]:
"""Returns layers present at a given z-position.

Args:
layer_stack: LayerStack
z: float
Returns:
List of layers
"""
Expand All @@ -93,11 +94,11 @@ def get_layers_at_z(layer_stack: LayerStack, z: float):
raise ValueError("Requested z-value is above the minimum layer_stack z")
for z_unique in intersection_z_dict.keys():
if z <= z_unique:
return intersection_z_dict[z_unique]
return list(intersection_z_dict[z_unique])
raise AssertionError("Could not find z-value in layer_stack z-range.")


def order_layer_stack(layer_stack: LayerStack):
def order_layer_stack(layer_stack: LayerStack) -> list[str]:
"""Orders layer_stack according to mesh_order.

Args:
Expand Down
33 changes: 18 additions & 15 deletions gplugins/common/utils/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,25 @@
from collections.abc import Sequence
from functools import partial
from itertools import combinations
from typing import Any

import gdsfactory as gf
import matplotlib.pyplot as plt
import numpy as np
import numpy.typing as npt
from matplotlib.axes import Axes


def _check_ports(sp: dict[str, np.ndarray], ports: Sequence[str]) -> None:
def _check_ports(
sp: dict[str, npt.NDArray[np.floating[Any]]], ports: Sequence[str]
) -> None:
"""Ensure ports exist in Sparameters."""
for port in ports:
if port not in sp:
raise ValueError(f"Did not find port {port!r} in {list(sp.keys())}")


def plot_sparameters(
sp: dict[str, np.ndarray],
sp: dict[str, npt.NDArray[np.floating[Any]]],
logscale: bool = True,
plot_phase: bool = False,
keys: tuple[str, ...] | None = None,
Expand All @@ -39,7 +43,7 @@ def plot_sparameters(

"""
w = sp["wavelengths"] * units
keys = keys or [key for key in sp if not key.lower().startswith("wav")]
keys = keys or tuple(key for key in sp if not key.lower().startswith("wav"))

for key in keys:
if with_simpler_input_keys:
Expand Down Expand Up @@ -74,9 +78,12 @@ def plot_sparameters(


def plot_imbalance(
sp: dict[str, np.ndarray], ports: Sequence[str], ax: plt.Axes | None = None
sp: dict[str, npt.NDArray[np.floating[Any]]],
ports: Sequence[str],
ax: Axes | None = None,
) -> None:
"""Plots imbalance in dB for coupler.

The imbalance is always defined between two ports, so this function plots the
imbalance between all unique port combinations.

Expand Down Expand Up @@ -107,7 +114,9 @@ def plot_imbalance(


def plot_loss(
sp: dict[str, np.ndarray], ports: Sequence[str], ax: plt.Axes | None = None
sp: dict[str, npt.NDArray[np.floating[Any]]],
ports: Sequence[str],
ax: Axes | None = None,
) -> None:
"""Plots loss dB for coupler.

Expand Down Expand Up @@ -137,7 +146,9 @@ def plot_loss(


def plot_reflection(
sp: dict[str, np.ndarray], ports: Sequence[str], ax: plt.Axes | None = None
sp: dict[str, npt.NDArray[np.floating[Any]]],
ports: Sequence[str],
ax: Axes | None = None,
) -> None:
"""Plots reflection in dB for coupler.

Expand Down Expand Up @@ -172,11 +183,3 @@ def plot_reflection(
plot_imbalance2x2 = partial(plot_imbalance, ports=["o1@0,o3@0", "o1@0,o4@0"])
plot_reflection1x2 = partial(plot_reflection, ports=["o1@0,o1@0"])
plot_reflection2x2 = partial(plot_reflection, ports=["o1@0,o1@0", "o2@0,o1@0"])

if __name__ == "__main__":
import gplugins as sim

sp = sim.get_sparameters_data_tidy3d(component=gf.components.mmi1x2)
# plot_sparameters(sp, logscale=False, keys=["o1@0,o2@0"])
# plot_sparameters(sp, logscale=False, keys=["S21"])
# plt.show()
19 changes: 12 additions & 7 deletions gplugins/gmsh/define_polysurfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@


def define_polysurfaces(
polygons_dict: dict,
polygons_dict: dict[str, Any],
layer_stack: LayerStack,
layer_physical_map: dict,
layer_meshbool_map: dict,
layer_physical_map: dict[str, Any],
layer_meshbool_map: dict[str, Any],
model: Any,
resolutions: dict,
resolutions: dict[str, Any] | None = None,
scale_factor: float = 1,
):
) -> list[PolySurface]:
"""Define meshwell polysurfaces dimtags from gdsfactory information."""
polysurfaces_list = []
polysurfaces_list: list[PolySurface] = []

if resolutions is None:
resolutions = {}
Expand All @@ -24,6 +24,11 @@ def define_polysurfaces(
if polygons_dict[layername].is_empty:
continue

layer_stack_ = layer_stack.layers.get(layername)

if layer_stack_ is None:
continue

polysurfaces_list.append(
PolySurface(
polygons=scale(
Expand All @@ -33,7 +38,7 @@ def define_polysurfaces(
),
model=model,
resolution=resolutions.get(layername, None),
mesh_order=layer_stack.layers.get(layername).mesh_order,
mesh_order=layer_stack_.mesh_order,
physical_name=layer_physical_map[layername]
if layername in layer_physical_map
else layername,
Expand Down
14 changes: 7 additions & 7 deletions gplugins/gmsh/uz_xsection_mesh.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# type: ignore
from __future__ import annotations

from collections.abc import Sequence
from typing import Any

import gdsfactory as gf
import numpy as np
Expand Down Expand Up @@ -206,12 +206,12 @@ def uz_xsection_mesh(
component: ComponentOrReference,
xsection_bounds: tuple[tuple[float, float], tuple[float, float]],
layer_stack: LayerStack,
layer_physical_map: dict,
layer_meshbool_map: dict,
resolutions: dict | None = None,
layer_physical_map: dict[str, Any],
layer_meshbool_map: dict[str, Any],
resolutions: dict[str, Any] | None = None,
default_characteristic_length: float = 0.5,
background_tag: str | None = None,
background_padding: Sequence[float, float, float, float, float, float] = (2.0,) * 6,
background_padding: Sequence[float] = (2.0,) * 6,
background_mesh_order: int | float = 2**63 - 1,
global_scaling: float = 1,
global_scaling_premesh: float = 1,
Expand All @@ -225,9 +225,9 @@ def uz_xsection_mesh(
n_threads: int = get_number_of_cores(),
gmsh_version: float | None = None,
interface_delimiter: str = "___",
background_remeshing_file=None,
background_remeshing_file: str | None = None,
optimization_flags: tuple[tuple[str, int]] | None = None,
**kwargs,
**kwargs: Any,
):
"""Mesh uz cross-section of component along line u = [[x1,y1] , [x2,y2]].

Expand Down
Loading
Loading