-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
200 changed files
with
53,633 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) |
Oops, something went wrong.