Skip to content

Commit

Permalink
add simulation
Browse files Browse the repository at this point in the history
  • Loading branch information
joamatab committed Aug 1, 2023
1 parent 61c84cb commit a019e5a
Show file tree
Hide file tree
Showing 200 changed files with 53,633 additions and 1 deletion.
130 changes: 130 additions & 0 deletions gplugins/add_simulation_markers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
"""Returns component with simulation markers."""
from __future__ import annotations

import warnings

import numpy as np

import gdsfactory as gf
from gdsfactory.add_pins import add_pin_rectangle
from gdsfactory.component import Component
from gdsfactory.components.bend_circular import bend_circular
from gdsfactory.pdk import get_layer_stack
from gdsfactory.technology import LayerLevel
from gdsfactory.typings import ComponentSpec, Layer


@gf.cell
def add_simulation_markers(
component: ComponentSpec = bend_circular,
port_margin: float = 3,
port_source_name: str = "o1",
layer_source: Layer = (110, 0),
layer_monitor: Layer = (101, 0),
port_source_offset: float = 0.2,
) -> Component:
r"""Returns new Component with simulation markers.
Args:
component: component spec.
port_margin: from port edge in um.
port_source_name: for input.
layer_source: for port marker.
layer_monitor: for port marker.
port_source_offset: distance from source to monitor in um.
.. code::
top view
________________________________
| |
| xmargin_left | port_extension
|<------> port_margin ||<-->
___|___________ _________||___
| \ / |
| \ / |
| ====== |
| / \ |
___|___________/ \__________|___
| | <-------->|
| |ymargin_bot xmargin_right|
| | |
|___|___________________________|
side view
________________________________
| | |
| | |
| zmargin_top |
|ymargin | |
|<---> _____ _|___ |
| | | | | |
| | | | | |
| |_____| |_____| |
| | |
| | |
| |zmargin_bot |
| | |
|_______|_______________________|
.. plot::
:include-source:
import gdsfactory as gf
from gplugins.add_simulation_markers import add_simulation_markers
c = gf.components.bend_circular()
c = add_simulation_markers(c)
c.plot()
"""
c = gf.Component()
component = gf.get_component(component)

ref = c << component
port_names = list(ref.ports.keys())

layer_stack = get_layer_stack()

if port_source_name not in port_names:
warnings.warn(f"port_source_name={port_source_name!r} not in {port_names}")
port_source = ref.get_ports_list()[0]
port_source_name = port_source.name
warnings.warn(f"Selecting port_source_name={port_source_name!r} instead.")

assert isinstance(
component, Component
), f"component needs to be a gf.Component, got Type {type(component)}"

# Add port monitors
for port_name in ref.ports.keys():
port = ref.ports[port_name]
add_pin_rectangle(c, port=port, port_margin=port_margin, layer=layer_monitor)
layer_stack.layers["monitor"] = LayerLevel(
layer=layer_monitor, thickness=2 * port_margin, zmin=-port_margin
)

# Add source
port = ref.ports[port_source_name]
angle_rad = np.radians(port.orientation)

port = port.move_polar_copy(angle=angle_rad, d=port_source_offset)
add_pin_rectangle(c, port=port, port_margin=port_margin, layer=layer_source)

layer_stack.layers["source"] = LayerLevel(
layer=layer_source, thickness=2 * port_margin, zmin=-port_margin
)

c.add_ports(component.ports)
c.copy_child_info(component)
return c


if __name__ == "__main__":
# c = gf.components.coupler_ring()
c = gf.components.mmi1x2()
c = add_simulation_markers(c)
c.show()
scene = c.to_3d()
scene.show()
107 changes: 107 additions & 0 deletions gplugins/convert_sparameters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
from __future__ import annotations

import pathlib
import re

import numpy as np
import pandas as pd
from tqdm.auto import tqdm

from gdsfactory.typings import PathType


def pandas_to_float64(
df: pd.DataFrame,
magnitude_suffix: str = "m",
phase_suffix: str = "a",
) -> pd.DataFrame:
"""Converts a pandas CSV sparameters from complex128 format to 2x float64 format.
Adds magnitude_suffix (default m) and phase_suffix (default a) to original keys.
"""
new_df = pd.DataFrame()

for key in df.keys():
if key != "wavelengths":
new_df[f"{key}{magnitude_suffix}"] = df[key].real
new_df[f"{key}{phase_suffix}"] = df[key].imag

new_df["wavelengths"] = df["wavelengths"]

return new_df


def pandas_to_numpy(df: pd.DataFrame, port_map=None) -> np.ndarray:
"""Converts a pandas CSV sparameters into a numpy array.
Fundamental mode starts at 0.
"""
s_headers = sorted({c[:-1] for c in df.columns if c.lower().startswith("s")})
idxs = sorted({idx for c in s_headers for idx in _s_header_to_port_idxs(c)})

if port_map is None:
port_map = {f"o{i}@0": i for i in idxs}
rev_port_map = {i: p for p, i in port_map.items()}
assert len(rev_port_map) == len(
port_map
), "Duplicate port indices found in port_map"

s_map = {
s: tuple(rev_port_map[i] for i in _s_header_to_port_idxs(s)) for s in s_headers
}

dfs = {
s: df[["wavelengths", f"{s}m", f"{s}a"]]
.copy()
.rename(columns={f"{s}m": "magnitude", f"{s}a": "phase"})
for s in s_map
}

S = dict(wavelengths=df["wavelengths"].values)
for key, df in dfs.items():
pm1, pm2 = s_map[key]
(p1, m1), (p2, m2) = pm1.split("@"), pm2.split("@")
name = f"{p1}@{m1},{p2}@{m2}"
S[name] = df["magnitude"].values * np.exp(1j * df["phase"].values)

return S


def csv_to_npz(filepath: PathType) -> pathlib.Path:
df = pd.read_csv(filepath)
sp = pandas_to_numpy(df)
filepath_npz = pathlib.Path(filepath).with_suffix(".npz")
np.savez_compressed(filepath_npz, **sp)
return filepath_npz


def convert_directory_csv_to_npz(dirpath: PathType) -> None:
dirpath = pathlib.Path(dirpath)
for filepath in tqdm(dirpath.glob("**/*.csv")):
try:
csv_to_npz(filepath)
except Exception as e:
print(filepath)
print(e)


def _s_header_to_port_idxs(s):
s = re.sub("[^0-9]", "", s)
inp, out = (int(i) for i in s)
return inp, out


if __name__ == "__main__":
# import matplotlib.pyplot as plt
from gdsfactory.config import PATH

filepath = PATH.sparameters / "mmi1x2_d542be8a.csv"
filepath = PATH.sparameters / "mmi1x2_00cc8908.csv"
filepath = PATH.sparameters / "mmi1x2_1f90b7ca.csv" # lumerical

convert_directory_csv_to_npz(PATH.sparameters)

# s = csv_to_npz(filepath)
# plt.plot(s["wavelengths"], np.abs(s["o1@0,o2@0"]) ** 2)
# plt.plot(s["wavelengths"], np.abs(s["o1@0,o3@0"]) ** 2)
# plt.show()
2 changes: 1 addition & 1 deletion gplugins/database/db_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def convert_to_db_format(sp: dict) -> pd.DataFrame:


if __name__ == "__main__":
import gdsfactory.simulation.gmeep as gm
import gplugins.gmeep as gm

component = gf.components.taper(length=100)
component_yaml = component.to_yaml()
Expand Down
27 changes: 27 additions & 0 deletions gplugins/devsim/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from __future__ import annotations

import devsim as tcad

from gdsfactory.config import logger
from gplugins.devsim.get_simulation_xsection import (
PINWaveguide,
alpha_to_k,
clear_devsim_cache,
dalpha_carriers,
dn_carriers,
k_to_alpha,
)
from gplugins.devsim.get_solver import DDComponent

logger.info(f"DEVSIM {tcad.__version__!r} installed at {tcad.__path__!r}")

__all__ = [
"dn_carriers",
"dalpha_carriers",
"alpha_to_k",
"k_to_alpha",
"PINWaveguide",
"DDComponent",
"clear_devsim_cache",
]
__version__ = "0.0.1"
97 changes: 97 additions & 0 deletions gplugins/devsim/doping.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from typing import Callable

import numpy as np
from pydantic import BaseModel

import gdsfactory as gf
from gdsfactory.typings import Layer


class DopingLayerLevel(BaseModel):
"""Level for doping layer.
Parameters:
layer: (GDSII Layer number, GDSII datatype).
type: str: "Acceptor" or "Donor".
z_profile: callable evaluating doping versus depth.
xy_profile: callable modulating z_profile at the edge of the layer.
"""

layer: Layer
type: str
z_profile: Callable
# xy_profile: Optional[Callable] = None # not implemented yet

class Config:
"""pydantic config."""

frozen = True
extra = "forbid"


cm3_to_um3 = 1e-12


def get_doping_info_generic(
n_conc: float = 1e17, # * cm3_to_um3,
p_conc: float = 1e17, # * cm3_to_um3,
npp_conc: float = 1e18, # * cm3_to_um3,
ppp_conc: float = 1e18, # * cm3_to_um3,
):
layermap = gf.generic_tech.LayerMap()

return {
"N": DopingLayerLevel(
layer=layermap.N,
type="Donor",
z_profile=step(n_conc),
),
"P": DopingLayerLevel(
layer=layermap.P,
type="Acceptor",
z_profile=step(p_conc),
),
"NPP": DopingLayerLevel(
layer=layermap.NPP,
type="Donor",
z_profile=step(npp_conc),
),
"PPP": DopingLayerLevel(
layer=layermap.PPP,
type="Acceptor",
z_profile=step(ppp_conc),
),
}


# def get_doping_xyz():
# """Returns acceptor vs x,y,z from DopingLayerLevel and a component."""

# def get_doping_density():
# """Returns acceptor vs x,y,z from DopingLayerLevel and a component."""


# def get_net_doping(component: Component, doping_info: Dict):
# """Returns net doping from DopingLayerLevel and a component."""

# for name, dopinglevel in doping_info.items():
# print("ok")


def step(c, zmin=-np.inf, zmax=np.inf):
"""Step function doping of value c, between zmin and zmax."""
return lambda y: c


# def step(c, zmin=-np.inf, zmax=np.inf):
# """Step function doping of value c, between zmin and zmax."""
# return lambda x, y, z: np.heaviside(c - zmin) - np.heaviside(c - zmax)

# def gaussian(n0, range, straggle):
# """Gaussian function doping of value c."""
# return n0*np.exp(-(z - range)**2/(2*straggle**2))

# def pearsonIV(n0, range, straggle):
# """Gaussian function doping of value c."""
# return n0*np.exp(-(z - range)**2/(2*straggle**2))
Loading

0 comments on commit a019e5a

Please sign in to comment.