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," 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)