216 lines
8.5 KiB
Python
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)
|