Files
mxpic_forge/mxpic/components/primitives/pic/bragg.py
T

216 lines
8.5 KiB
Python

import nazca as nd
import numpy as np
from ...geometry import *
from ...routing import Route
from . import MDM
class Bragg_apodized:
"""
Bragg apodized primitive component.
This component builds the Bragg apodized layout cell.
Parameters
----------
Period : float, optional
Value for the Period parameter. Default is 0.3.
w : float, optional
Width parameter in microns. Default is 1.1.
xs : str, optional
Layer or cross-section name used by the device. Default is 'strip'.
etch_type : str, optional
Value for the etch_type parameter. Default is 'FETCH'.
etch_shape : str, optional
Value for the etch_shape parameter. Default is 'rectangle'.
N : int, optional
Value for the N parameter. Default is 200.
eta_etch : float, optional
Value for the eta_etch parameter. Default is 0.5.
dT : float, optional
Value for the dT parameter. Default is 0.15.
b : int, optional
Value for the b parameter. Default is 10.
eta_ds : float, optional
Value for the eta_ds parameter. Default is 0.5.
show_pins : bool, optional
Whether to draw pin markers in the generated layout. Default is False.
"""
def __init__(self,
Period: float = 0.3,
w: float = 1.1,
xs: str = 'strip',
etch_type: str = 'FETCH',
etch_shape: str = 'rectangle',
N: int = 200,
eta_etch: float = 0.5,
dT: float = 0.15, ## etch in depth
b: int = 10,
eta_ds: float = 0.5,
show_pins: bool=False) -> None:
"""_summary_
Args:
Period (float, optional): Period. Defaults to 0.3.
w (float, optional): width of the main waveguide. Defaults to 1.1.
xs (str, optional): Xsection of the waveguide. Defaults to 'strip'.
etch_type (str, optional): Etch type, FETCH, METCH, SETCH. Defaults to 'FETCH'.
etch_shape (str, optional): rectangle or cicle. Defaults to 'rectangle'.
N (int, optional): Total Period number. Defaults to 200.
eta_etch (float, optional): etch duty cycle. Defaults to 0.5.
dT (float, optional): etch depth into waveguide. Defaults to 0.15.
show_pins (bool, optional): Flag to display pins. Defaults to False.
"""
self.Period = Period
self.w = w
self.xs = xs
self.N = N
self.eta_etch = eta_etch
self.etch_shape = etch_shape
self.dT = dT
self.b = b
self.show_pins = show_pins
if (nd.get_layer(layer="STRIP_TRE") == "STRIP_TRE"): ## CUMEC, IMEC
self.positive = False
if (etch_shape=='circle'):
if (etch_type=="FETCH"):
layer_etch = "STRIP_HOL"
elif (etch_type=="METCH"):
layer_etch = "RIB_HOL"
elif (etch_type=="SETCH"):
layer_etch = "SRIB_HOL"
elif (etch_shape=='rectangle'):
if (etch_type=="FETCH"):
layer_etch = "STRIP_TRE"
elif (etch_type=="METCH"):
layer_etch = "RIB_TRE"
elif (etch_type=="SETCH"):
layer_etch = "SRIB_TRE"
else : ## AMF, ANT
self.positive = True
if (etch_type=="FETCH"):
layer_etch = None
elif (etch_type=="METCH"):
layer_etch = "RIB_COR"
elif (etch_type=="SETCH"):
layer_etch = "SRIB_COR"
self.eta_ds = eta_ds
self.layer_etch = layer_etch
if (layer_etch!=None):
if (nd.get_layer(layer_etch)!=layer_etch):
layer_etch=None
print("WARNING: In mxpic::passive::Grat_1D_single_etch, <layer_etch>::",layer_etch," not defined in tapeout")
if (self.positive):
self.cell = self.generate_positive()
else:
self.cell = self.generate_negative()
def generate_positive(self):
with nd.Cell(instantiate=False) as C:
w_core =self.w - self.dT*2
L_brg = self.Period*self.N
INSTR = nd.strt(length=L_brg,width=w_core,xs=self.xs).put(0,0,0)
for idx in range(0,self.N):
_X_ = idx*self.Period
_Y_ = w_core/2 + self.dT/2
ds = self.Period*self.eta_ds * np.exp(-self.b*(_X_-L_brg/2)*(_X_-L_brg/2)/L_brg/L_brg )
nd.strt(length=self.Period*(1-self.eta_etch),width=self.dT,xs=self.xs).put(_X_,_Y_,0)
nd.strt(length=self.Period*(1-self.eta_etch),width=self.dT,xs=self.xs).put(_X_+ds,-_Y_,0)
## revised in 2026.06.07 by Qin Yue
# legacy: nd.Pin(name='a1',pin=INSTR.pin['a0'],width=self.w).put()
nd.Pin(name='opt_a1',pin=INSTR.pin['a0'],width=self.w,type="optical:").put()
## revised in 2026.06.07 by Qin Yue
# legacy: nd.Pin(name='b1',pin=INSTR.pin['b0'],width=self.w).put()
nd.Pin(name='opt_b1',pin=INSTR.pin['b0'],width=self.w,type="optical:").put()
if (self.show_pins):
nd.put_stub(pinsize=3)
return C
def generate_negative(self):
with nd.Cell(instantiate=False) as C:
w_core =self.w - self.dT*2
L_brg = self.Period*self.N
INSTR = nd.strt(length=L_brg,width=self.w,xs=self.xs).put(0,0,0)
## revised in 2026.06.07 by Qin Yue
# legacy: nd.Pin(name='a1',pin=INSTR.pin['a0'],width=self.w).put()
nd.Pin(name='opt_a1',pin=INSTR.pin['a0'],width=self.w,type="optical:").put()
## revised in 2026.06.07 by Qin Yue
# legacy: nd.Pin(name='b1',pin=INSTR.pin['b0'],width=self.w).put()
nd.Pin(name='opt_b1',pin=INSTR.pin['b0'],width=self.w,type="optical:").put()
for idx in range(0,self.N):
_X_ = idx*self.Period + (1-self.eta_etch)*self.Period
_Y_ = w_core/2 + self.dT/2
ds = self.Period*self.eta_ds * np.exp(-self.b*(_X_-L_brg/2)*(_X_-L_brg/2)/L_brg/L_brg )
if (self.etch_shape=='circle'):
circle(radius=self.Period*(self.eta_etch)/4,width=self.Period*(self.eta_etch)/2,theta_start=0,theta_stop=360,
n_points=12,layer=self.layer_etch).cell.put(_X_,_Y_,0)
circle(radius=self.Period*(self.eta_etch)/4,width=self.Period*(self.eta_etch)/2,theta_start=0,theta_stop=360,
n_points=12,layer=self.layer_etch).cell.put(_X_+ds,-_Y_,0)
else:
nd.strt(length=self.Period*(self.eta_etch),width=self.dT,layer=self.layer_etch).put(_X_,_Y_,0)
nd.strt(length=self.Period*(self.eta_etch),width=self.dT,layer=self.layer_etch).put(_X_+ds,-_Y_,0)
if (self.show_pins):
nd.put_stub(pinsize=3)
return C
class Bragg(Bragg_apodized):
"""
Bragg primitive component.
This component builds the Bragg layout cell.
Parameters
----------
Period : float, optional
Value for the Period parameter. Default is 0.3.
w : float, optional
Width parameter in microns. Default is 1.1.
xs : str, optional
Layer or cross-section name used by the device. Default is 'strip'.
etch_type : str, optional
Value for the etch_type parameter. Default is 'FETCH'.
etch_shape : str, optional
Value for the etch_shape parameter. Default is 'rectangle'.
N : int, optional
Value for the N parameter. Default is 200.
eta_etch : float, optional
Value for the eta_etch parameter. Default is 0.5.
dT : float, optional
Value for the dT parameter. Default is 0.15.
show_pins : bool, optional
Whether to draw pin markers in the generated layout. Default is False.
"""
def __init__(self, Period: float=0.3,
w: float=1.1,
xs: str='strip',
etch_type: str='FETCH',
etch_shape: str='rectangle',
N: int=200,
eta_etch: float=0.5,
dT: float=0.15,
show_pins: bool=False) -> None:
super().__init__(Period, w, xs, etch_type, etch_shape, N, eta_etch, dT, b=0, eta_ds=0, show_pins=show_pins)