New forge coding added
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
from typing import Optional
|
||||
from turtle import shape
|
||||
import nazca as nd
|
||||
import numpy as np
|
||||
import math
|
||||
|
||||
from .taper import taper_xs2xs
|
||||
from ...routing import Route
|
||||
|
||||
from ...structures import *
|
||||
from ....technologies import *
|
||||
|
||||
class PBS_3wg:
|
||||
def __init__(self,
|
||||
name: Optional[str] = None,
|
||||
xs: str = 'strip',
|
||||
Lcp: float = 11.7 ,
|
||||
w1_tp: float = 0.55,
|
||||
w2_tp: float = 0.3,
|
||||
w_m: float = 0.45,
|
||||
gap: float = 0.25,
|
||||
R_bend: int = 20,
|
||||
A_bend: float = 7.5,
|
||||
w_wg: float = 0.45,
|
||||
show_pins: bool = False,
|
||||
sharp_patch: bool = True ) -> None:
|
||||
|
||||
self.Lcp = Lcp
|
||||
self.xs = xs
|
||||
self.w1_tp = w1_tp
|
||||
self.w2_tp = w2_tp
|
||||
self.w_m = w_m
|
||||
self.gap = gap
|
||||
self.R_bend = R_bend
|
||||
self.A_bend = A_bend
|
||||
self.w_wg = w_wg
|
||||
|
||||
self.name = name
|
||||
if (self.name==None):
|
||||
self.instantiate = False
|
||||
else :
|
||||
self.instantiate = True
|
||||
|
||||
|
||||
self.cell = self.generate_gds(show_pins=show_pins, sharp_patch=sharp_patch)
|
||||
|
||||
def generate_gds(self,show_pins=False,sharp_patch = True):
|
||||
w_crack = 0.002
|
||||
with nd.Cell(instantiate=self.instantiate,name=self.name) as C:
|
||||
|
||||
nd.strt(length=self.Lcp,width=self.w_m,xs=self.xs).put(-self.Lcp/2,0,0)
|
||||
|
||||
tp_U = nd.taper(length=self.Lcp,width1=self.w1_tp,width2=self.w2_tp,xs=self.xs,shift=-(self.w1_tp-self.w2_tp)/2).put(-self.Lcp/2,self.w1_tp/2+self.gap+self.w_m/2,0)
|
||||
tp_D = nd.taper(length=self.Lcp,width1=self.w2_tp,width2=self.w1_tp,xs=self.xs,shift=(self.w2_tp-self.w1_tp)/2).put(-self.Lcp/2,-self.w2_tp/2-self.gap-self.w_m/2,0)
|
||||
|
||||
Att_U = nd.bend(angle=self.A_bend,radius=self.R_bend,xs=self.xs,width=self.w1_tp).put(tp_U.pin['a0'],flip=1)
|
||||
Att_U = nd.bend(angle=self.A_bend,radius=self.R_bend,xs=self.xs,width=self.w1_tp).put(flip=0)
|
||||
|
||||
Att_D = nd.bend(angle=self.A_bend,radius=self.R_bend,xs=self.xs,width=self.w2_tp).put(tp_D.pin['a0'],flip=0)
|
||||
Att_D = nd.bend(angle=self.A_bend,radius=self.R_bend,xs=self.xs,width=self.w2_tp).put(flip=1)
|
||||
|
||||
if (self.w_wg!=None and self.w_wg>0) :
|
||||
Att_D = nd.taper(length=5,width1=self.w2_tp,width2=self.w_wg,xs=self.xs).put(Att_D.pin['b0'])
|
||||
Att_U = nd.taper(length=5,width1=self.w1_tp,width2=self.w_wg,xs=self.xs).put(Att_U.pin['b0'])
|
||||
|
||||
nd.Pin(name='a1',pin=Att_U.pin['b0']).put()
|
||||
nd.Pin(name='a2',pin=Att_D.pin['b0']).put()
|
||||
|
||||
nd.strt(length=w_crack,width=self.w_wg,xs=self.xs).put(Att_U.pin['b0'].x-w_crack/2,Att_U.pin['b0'].y,0)
|
||||
nd.strt(length=w_crack,width=self.w_wg,xs=self.xs).put(Att_D.pin['b0'].x-w_crack/2,Att_D.pin['b0'].y,0)
|
||||
|
||||
Att_U = nd.bend(angle=self.A_bend,radius=self.R_bend,xs=self.xs,width=self.w2_tp).put(tp_U.pin['b0'],flip=0)
|
||||
Att_U = nd.bend(angle=self.A_bend,radius=self.R_bend,xs=self.xs,width=self.w2_tp).put(flip=1)
|
||||
|
||||
Att_D = nd.bend(angle=self.A_bend,radius=self.R_bend,xs=self.xs,width=self.w1_tp).put(tp_D.pin['b0'],flip=1)
|
||||
Att_D = nd.bend(angle=self.A_bend,radius=self.R_bend,xs=self.xs,width=self.w1_tp).put(flip=0)
|
||||
|
||||
if (self.w_wg!=None and self.w_wg>0) :
|
||||
Att_D = nd.taper(length=5,width1=self.w1_tp,width2=self.w_wg,xs=self.xs).put(Att_D.pin['b0'])
|
||||
Att_U = nd.taper(length=5,width1=self.w2_tp,width2=self.w_wg,xs=self.xs).put(Att_U.pin['b0'])
|
||||
|
||||
nd.Pin(name='b1',pin=Att_U.pin['b0']).put()
|
||||
nd.Pin(name='b2',pin=Att_D.pin['b0']).put()
|
||||
|
||||
nd.strt(length=w_crack,width=self.w_wg,xs=self.xs).put(Att_U.pin['b0'].x-w_crack/2,Att_U.pin['b0'].y,0)
|
||||
nd.strt(length=w_crack,width=self.w_wg,xs=self.xs).put(Att_D.pin['b0'].x-w_crack/2,Att_D.pin['b0'].y,0)
|
||||
|
||||
if (show_pins):
|
||||
nd.put_stub()
|
||||
|
||||
return C
|
||||
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
from typing import Optional
|
||||
import nazca as nd
|
||||
import numpy as np
|
||||
import math
|
||||
from ...routing import Route
|
||||
|
||||
from ...structures import *
|
||||
from ....technologies import *
|
||||
|
||||
import pandas as pd
|
||||
from ...structures import _my_polygon
|
||||
from scipy.interpolate import CubicSpline
|
||||
from ...basic import __cell_arg__
|
||||
|
||||
class YBranch:
|
||||
def __init__(self,
|
||||
name : str = None,
|
||||
xs : str = 'strip',
|
||||
w : 'list|np.ndarray' = [1.2,1.0,1.8,1.2,1.0,1.2,1.2],
|
||||
L : float = 6,
|
||||
R_att : float = 10,
|
||||
A_att : float = 10,
|
||||
w_port : float = 0.45,
|
||||
show_pins : bool = False,
|
||||
sharp_patch : bool = True,
|
||||
|
||||
res : float = 0.1,
|
||||
) -> None:
|
||||
"""_summary_
|
||||
|
||||
Args:
|
||||
name (str, optional): _description_. Defaults to None.
|
||||
xs (str, optional): _description_. Defaults to 'strip'.
|
||||
layer (str, optional): _description_. Defaults to None.
|
||||
w_in (float, optional): input port width. Defaults to 1.2.
|
||||
w_out (float, optional): output port width, for main body. Defaults to 1.2.
|
||||
w (list|np.ndarray, optional): _description_. Defaults to [1.2,1.0,1.8,1.2,1.0,1.2].
|
||||
L (float, optional): _description_. Defaults to 6.
|
||||
R_att (float, optional): _description_. Defaults to 10.
|
||||
A_att (float, optional): _description_. Defaults to 10.
|
||||
w_port (float, optional): _description_. Defaults to 0.45.
|
||||
show_pins (bool, optional): _description_. Defaults to False.
|
||||
res (float, optional): _description_. Defaults to 0.1.
|
||||
"""
|
||||
|
||||
|
||||
self.name = name
|
||||
|
||||
if (name!=None):
|
||||
self.instantiate = True
|
||||
else :
|
||||
self.instantiate = False
|
||||
|
||||
self.w = w
|
||||
self.L = L
|
||||
self.res = res
|
||||
self.R_att = R_att
|
||||
self.A_att = A_att
|
||||
self.w_port = w_port
|
||||
self.xs = xs
|
||||
|
||||
self.cell = self.generate_gds(show_pins=show_pins,sharp_patch=sharp_patch)
|
||||
|
||||
def generate_gds(self,show_pins=False,sharp_patch=True):
|
||||
with nd.Cell(name=self.name,instantiate=self.instantiate) as C:
|
||||
|
||||
w = np.r_[self.w]
|
||||
|
||||
n_sects = len(self.w)-1
|
||||
res = self.L/n_sects
|
||||
n_points = int(self.L/self.res)+1
|
||||
L = np.linspace(0,self.L,n_sects+1)
|
||||
L_act = np.linspace(0,self.L,n_points)
|
||||
|
||||
f = CubicSpline(L,w) ## cubic spline interpolant
|
||||
|
||||
w_act = f(L_act)
|
||||
|
||||
|
||||
for layers,growx,growy,acc in nd.layeriter(xs=self.xs):
|
||||
(a1,b1), (a2,b2),c1,c2 = growx
|
||||
|
||||
w_cur = w_act*(a1-a2) + (b1-b2)
|
||||
if (b1!=0 and b2!=0):
|
||||
w_cur = max(w_cur)*np.ones(np.shape(w_cur))
|
||||
vtx_x = np.r_[L_act,np.flip(L_act,0)]
|
||||
vtx_y = np.r_[w_cur/2,-np.flip(w_cur/2,0)]
|
||||
vtx = np.c_[vtx_x,vtx_y]
|
||||
_my_polygon(layer_wg=layers,vtx=vtx).put(0,0,0)
|
||||
|
||||
temp = circle(xs=self.xs,radius=self.R_att,theta_start=0,theta_stop=self.A_att,width=self.w_port).cell.put('a1',self.L,self.w[-1]/2 - self.w_port/2,0)
|
||||
temp = circle(xs=self.xs,radius=self.R_att,theta_start=-self.A_att,theta_stop=0,width=self.w_port).cell.put('a1',temp.pin['b1'],flip=1)
|
||||
nd.Pin(name='b1',width=self.w_port).put(temp.pin['b1'])
|
||||
|
||||
temp = circle(xs=self.xs,radius=self.R_att,theta_start=0,theta_stop=self.A_att,width=self.w_port).cell.put('a1',self.L,-self.w[-1]/2 + self.w_port/2,0,flip=1)
|
||||
temp = circle(xs=self.xs,radius=self.R_att,theta_start=-self.A_att,theta_stop=0,width=self.w_port).cell.put('a1',temp.pin['b1'],flip=0)
|
||||
nd.Pin(name='b2',width=self.w_port).put(temp.pin['b1'])
|
||||
|
||||
nd.Pin(name='a1',width=self.w[0]).put(0,0,180)
|
||||
|
||||
if (show_pins):
|
||||
nd.put_stub()
|
||||
|
||||
return C
|
||||
|
||||
|
||||
class Ybranch_3wg:
|
||||
def __init__(self,
|
||||
name: Optional[str] = None,
|
||||
w0:float=0.4,
|
||||
w1:float=0.2,
|
||||
gap:float=0.18,
|
||||
Lcp:float=20,
|
||||
xs:str='strip',
|
||||
w_wg:float=0.45,
|
||||
R0:float=10,
|
||||
angle:float=20,
|
||||
L_attach:float=3,
|
||||
L_in_tp:float=3,
|
||||
sharp_patch:bool=True) -> None:
|
||||
'''
|
||||
Initialization of a symmetric tapered coupler for 3dB coupling
|
||||
|
||||
Paras :
|
||||
1. taper part
|
||||
- w0/w1 [um] (Default: 0.4/0.2um)
|
||||
Input/Output taper width
|
||||
- L [um] (Default: 20um)
|
||||
taper length of the coupling area
|
||||
- gap [um] (Default : 0.18)
|
||||
vertical gap between the taper couplers
|
||||
- xs [str] (Default : 'strip')
|
||||
xsection of the waveguide
|
||||
|
||||
2. attachment part
|
||||
- w_wg [um] (Default: 0.45um)
|
||||
Input&ouput waveguide width
|
||||
- L_attach [um] (Default: 3um)
|
||||
Input&ouput straight waveguide length
|
||||
- L_in_taper [um] (Default: 3um)
|
||||
Input&ouput taper waveguide length for connecting w_wg and w0
|
||||
- R0 [um] (Default: 10um)
|
||||
Ouput bending radius
|
||||
- angle [um] (Default: 10um)
|
||||
Ouput bending angle
|
||||
|
||||
Cell:
|
||||
- pins
|
||||
input [a1]
|
||||
outpuit [b1][b2]
|
||||
'''
|
||||
self.name = name
|
||||
if (self.name==None):
|
||||
self.instantiate = False
|
||||
else :
|
||||
self.instantiate = True
|
||||
|
||||
self.w0 = w0
|
||||
self.w1 = w1
|
||||
self.gap = gap
|
||||
self.Lcp = Lcp
|
||||
self.xs = xs
|
||||
self.w_wg = w_wg
|
||||
self.R0 = R0
|
||||
self.angle = angle
|
||||
self.L_attach = L_attach
|
||||
self.L_in_tp = L_in_tp
|
||||
|
||||
self.cell = self.generate_gds(sharp_patch=sharp_patch)
|
||||
self.L = np.abs(self.cell.pin['a1'].x - self.cell.pin['b1'].x)
|
||||
|
||||
def generate_gds(self,sharp_patch,err_asy=0):
|
||||
with nd.Cell(instantiate=self.instantiate,name=self.name) as C:
|
||||
|
||||
w0 = self.w0
|
||||
w1 = self.w1
|
||||
Lcp = self.Lcp
|
||||
gap = self.gap
|
||||
xs = self.xs
|
||||
w_wg = self.w_wg
|
||||
L_attach = self.L_attach
|
||||
L_in_tp = self.L_in_tp
|
||||
angle = self.angle
|
||||
R0 = self.R0
|
||||
|
||||
t_mid = nd.taper(width1=w0,width2=w1,length=Lcp,xs=xs).put(0,0,0)
|
||||
t_u = nd.taper(width2=w0,width1=w1,length=Lcp,xs=xs).put(0,w1/2+w0/2+gap,0)
|
||||
t_d = nd.taper(width2=w0,width1=w1,length=Lcp,xs=xs).put(0,-(w1/2+w0/2+gap),0)
|
||||
t_in = nd.taper(width1=w_wg,width2=w0,length=L_in_tp,xs=xs).put(-L_in_tp,0,0)
|
||||
t_in = nd.strt(width=w_wg,length=L_attach,xs=xs).put(t_in.pin['a0'],flip=0)
|
||||
nd.Pin(name='a1',pin=t_in.pin['b0']).put()
|
||||
|
||||
au = nd.bend(radius=R0,angle=angle,xs=xs,width=w0).put(t_u.pin['b0'],flip=0)
|
||||
au = nd.bend(radius=R0,angle=angle,xs=xs,width=w0).put(au.pin['b0'],flip=1)
|
||||
au = nd.taper(width1=w0,width2=w_wg,length=L_in_tp,xs=xs).put(au.pin['b0'],flip=0)
|
||||
au = nd.strt(width=w_wg,length=L_attach,xs=xs).put(au.pin['b0'],flip=0)
|
||||
nd.Pin(name='b1',pin=au.pin['b0']).put()
|
||||
|
||||
ad = nd.bend(radius=R0,angle=angle,xs=xs,width=w0).put(t_d.pin['b0'],flip=1)
|
||||
ad = nd.bend(radius=R0,angle=angle,xs=xs,width=w0).put(ad.pin['b0'],flip=0)
|
||||
ad = nd.taper(width1=w0,width2=w_wg,length=L_in_tp,xs=xs).put(ad.pin['b0'],flip=0)
|
||||
ad = nd.strt(width=w_wg,length=L_attach,xs=xs).put(ad.pin['b0'],flip=0)
|
||||
nd.Pin(name='b2',pin=ad.pin['b0']).put()
|
||||
|
||||
|
||||
if (sharp_patch==True):
|
||||
dY = np.abs(ad.pin['b0'].y-au.pin['b0'].y)+w_wg
|
||||
for layers,growx,growy,acc in nd.layeriter(xs=xs):
|
||||
(a1,b1), (a2,b2),c1,c2 = growx
|
||||
if (b1!=0 and b2!=0):
|
||||
L_patch = dY*(a1-a2)+(b1-b2)
|
||||
W_patch = dY*(a1-a2)+(b1-b2)
|
||||
nd.strt(length=W_patch,width=L_patch,layer=layers).put(ad.pin['b0'].x,0,0)
|
||||
return C
|
||||
|
||||
def generate_test_gds(self,gc,dX_gc2gc=400,dY_gc2gc=80,sharp_patch = True,Rbend=15):
|
||||
with nd.Cell(instantiate=False) as C:
|
||||
|
||||
|
||||
gc_cell = __cell_arg__(arg=gc,arg_name="gc",func_name="mxpic::Ybranch_3wg::generate_test_gds")
|
||||
|
||||
inst = self.cell.put('a1',-self.L/2,0,0)
|
||||
|
||||
gc_In = gc_cell.put('g1',-dX_gc2gc/2,0,180)
|
||||
gc_O1 = gc_cell.put('g1',dX_gc2gc/2, dY_gc2gc/2,0)
|
||||
gc_O2 = gc_cell.put('g1',dX_gc2gc/2,-dY_gc2gc/2,0)
|
||||
pic_strip = Route(radius=Rbend,width=self.w_wg,xs=self.xs)
|
||||
|
||||
pic_strip.taper(pin=gc_O1.pin['g1'],width1=gc_O1.pin['g1'].width,width2=self.w_wg,length=5,arrow=False)
|
||||
pic_strip.sbend_p2p(original_function=not sharp_patch, pin2=inst.pin['b1'],arrow=False).put()
|
||||
|
||||
pic_strip.taper(pin=gc_O2.pin['g1'],width1=gc_O2.pin['g1'].width,width2=self.w_wg,length=5,arrow=False)
|
||||
pic_strip.sbend_p2p(original_function=not sharp_patch, pin2=inst.pin['b2'],arrow=False).put()
|
||||
pic_strip.taper_p2p(pin1=gc_In.pin['g1'],pin2=inst.pin['a1'],arrow=False).put()
|
||||
|
||||
return C
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
from .gratings import GC_STD_1D,GC_STD_2D
|
||||
from .gratings import Grating_2D_Hole, Grating_2D_Hole_3Rec, Grating_2D_Hole_4Rec
|
||||
from .gratings import Nano_ant
|
||||
from .gratings import FA
|
||||
|
||||
from .rings import STD_PIC_Rings,AED_ring
|
||||
|
||||
from .couplers import ring_bus_wg
|
||||
from .couplers import DC
|
||||
from .couplers import DC_bend
|
||||
from .couplers import DC_pX_3sg
|
||||
from .couplers import ADC_STD_2x2
|
||||
from .couplers import BS_tdc
|
||||
from .couplers import MDM
|
||||
from .couplers import DC_pX_3sg
|
||||
|
||||
from .taper import taper_xs2xs,PSR, transition
|
||||
|
||||
from .spiral import spiral,Spiral_Cicle_STD,Spiral_Rect_STD,spiral_circle,Spiral_Cicle_MM,spiral_rectangle
|
||||
|
||||
from .cross import Cross,Cross_Sine
|
||||
|
||||
from .mmi import MMI_ML,MMI_STD
|
||||
|
||||
from .bragg import Bragg,Bragg_apodized
|
||||
|
||||
from .PBS import PBS_3wg
|
||||
|
||||
from .YBS import YBranch,Ybranch_3wg
|
||||
|
||||
from .racetrack import RacetrackResonator,Racetrack_MM_Adddrop,Racetrack_MM_Allpass,Racetrack_STD_Allpass
|
||||
@@ -0,0 +1,151 @@
|
||||
import nazca as nd
|
||||
import numpy as np
|
||||
|
||||
|
||||
from ...structures import *
|
||||
|
||||
from ...routing import Route
|
||||
from . import MDM
|
||||
|
||||
|
||||
class Bragg_apodized:
|
||||
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)
|
||||
|
||||
nd.Pin(name='a1',pin=INSTR.pin['a0'],width=self.w).put()
|
||||
nd.Pin(name='b1',pin=INSTR.pin['b0'],width=self.w).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)
|
||||
nd.Pin(name='a1',pin=INSTR.pin['a0'],width=self.w).put()
|
||||
nd.Pin(name='b1',pin=INSTR.pin['b0'],width=self.w).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):
|
||||
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)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,134 @@
|
||||
from typing import Optional
|
||||
import nazca as nd
|
||||
import numpy as np
|
||||
import math
|
||||
from ...routing import Route
|
||||
|
||||
from ...structures import *
|
||||
from ....technologies import *
|
||||
|
||||
import pandas as pd
|
||||
from ...structures import _my_polygon
|
||||
|
||||
class Cross:
|
||||
def __init__(self,
|
||||
name: Optional[str] = None,
|
||||
L: list = [0 , 1, 2, 3, 4],
|
||||
w: list = [0.5,0.45,0.6,0.4,0.5],
|
||||
xs : str = 'strip',
|
||||
show_pins: bool=False
|
||||
) -> None:
|
||||
|
||||
self.name = name
|
||||
if (self.name==None):
|
||||
self.instantiate = False
|
||||
else :
|
||||
self.instantiate = True
|
||||
|
||||
self.L = L
|
||||
self.w = w
|
||||
self.xs =xs
|
||||
|
||||
self.cell = self.generate_gds(show_pins=show_pins)
|
||||
|
||||
def generate_gds(self,show_pins):
|
||||
with nd.Cell(instantiate=self.instantiate,name=self.name) as C:
|
||||
|
||||
for layers,growx,growy,acc in nd.layeriter(xs=self.xs):
|
||||
(a1,b1), (a2,b2),c1,c2 = growx
|
||||
|
||||
L = np.array(self.L)
|
||||
|
||||
L_arm = np.max(L)
|
||||
self.L_arm = L_arm
|
||||
w = np.array(self.w) + b1 - b2
|
||||
vtx_x = np.r_[L,np.flip(L,0)]
|
||||
vtx_y = np.r_[w/2,-np.flip(w,0)/2]
|
||||
|
||||
vtx = np.c_[vtx_x,vtx_y]
|
||||
_my_polygon(layer_wg=layers,vtx=vtx).put(-L_arm,0,0)
|
||||
_my_polygon(layer_wg=layers,vtx=vtx).put(0,-L_arm,90)
|
||||
_my_polygon(layer_wg=layers,vtx=vtx).put(0,L_arm,-90)
|
||||
_my_polygon(layer_wg=layers,vtx=vtx).put(L_arm,0,180)
|
||||
|
||||
nd.Pin(name='a1',width=self.w[0]).put(-L_arm,0,180)
|
||||
nd.Pin(name='a2',width=self.w[0]).put( 0,-L_arm,-90)
|
||||
nd.Pin(name='b2',width=self.w[0]).put( 0, L_arm, 90)
|
||||
nd.Pin(name='b1',width=self.w[0]).put( L_arm,0,0)
|
||||
|
||||
if (show_pins):
|
||||
nd.put_stub()
|
||||
|
||||
return C
|
||||
|
||||
def generate_test_gds(self,gc,num=5,dX_gc2gc=400,w_end=0.2,L_end=10):
|
||||
with nd.Cell(instantiate=False) as C:
|
||||
|
||||
if (isinstance(gc,nd.Cell)):
|
||||
gc_cell = gc
|
||||
elif (hasattr(gc,'cell')):
|
||||
gc_cell = gc.cell
|
||||
else :
|
||||
raise Exception("ERROR: In <mxpiv::passive::cross::generate_test_gds>, <gc> is not recongized")
|
||||
|
||||
res = self.L_arm*2
|
||||
|
||||
dX = res*1.5
|
||||
|
||||
pic_strip = Route(radius=10,width=self.w[0],xs=self.xs)
|
||||
|
||||
gc_In = gc_cell.put('g1',-dX_gc2gc/2,0,180)
|
||||
pin_pre = gc_In.pin['g1']
|
||||
for _idx_ in range(0,num):
|
||||
inst = self.cell.put('a0',_idx_*dX - (num/2 - 1/2)*dX)
|
||||
pic_strip.strt_p2p(pin1=pin_pre,pin2=inst.pin['a1'],arrow=False).put()
|
||||
pin_pre = inst.pin['b1']
|
||||
|
||||
nd.taper(length=L_end/2,width1=self.w[0],width2=w_end,xs=self.xs).put(inst.pin['b2'])
|
||||
nd.strt(length=L_end/2,width=w_end,xs=self.xs).put()
|
||||
nd.taper(length=L_end/2,width1=self.w[0],width2=w_end,xs=self.xs).put(inst.pin['a2'])
|
||||
nd.strt(length=L_end/2,width=w_end,xs=self.xs).put()
|
||||
|
||||
gc_Out = gc_cell.put('g1', dX_gc2gc/2,0,0)
|
||||
pic_strip.strt_p2p(pin1=pin_pre,pin2=gc_Out.pin['g1'],arrow=False).put()
|
||||
|
||||
|
||||
|
||||
return C
|
||||
|
||||
class Cross_Sine(Cross):
|
||||
def __init__(self,
|
||||
name: Optional[str] = None,
|
||||
res: list = [1,1,1,1],
|
||||
w: list = [0.5,0.45,0.6,0.4,0.5],
|
||||
xs : str = 'strip',
|
||||
n_points: int = 4,
|
||||
show_pins: bool=False
|
||||
) -> None:
|
||||
|
||||
|
||||
L = 0
|
||||
for _idx_ in range(0,len(w)-1):
|
||||
L_sect = np.linspace(L,L+res[_idx_],n_points)
|
||||
L = L+res[_idx_]
|
||||
w_sect = -np.cos((L_sect-L)/res[_idx_]*np.pi)*(w[_idx_]-w[_idx_+1])/2 + (w[_idx_]+w[_idx_+1])/2
|
||||
|
||||
if (_idx_==0):
|
||||
L_crs = L_sect
|
||||
w_crs = w_sect
|
||||
else :
|
||||
L_crs = np.r_[L_crs,L_sect]
|
||||
w_crs = np.r_[w_crs,w_sect]
|
||||
|
||||
|
||||
L_crs = np.r_[L_crs,L_crs[-1]+w_crs[-1]/2]
|
||||
w_crs = np.r_[w_crs,w_crs[-1]]
|
||||
|
||||
|
||||
|
||||
|
||||
super().__init__(name=name,L=L_crs,w=w_crs,xs=xs,show_pins=show_pins)
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,213 @@
|
||||
from typing import Optional
|
||||
from turtle import shape
|
||||
import nazca as nd
|
||||
import numpy as np
|
||||
import math
|
||||
|
||||
from .taper import taper_xs2xs
|
||||
from ...routing import Route
|
||||
|
||||
from ...structures import *
|
||||
from ....technologies import *
|
||||
|
||||
from ...structures import _my_polygon,Conchoid
|
||||
|
||||
""" Mono layer MMI """
|
||||
class MMI_ML:
|
||||
def __init__(self,
|
||||
name: Optional[str]=None,
|
||||
L_arm: list=[10],
|
||||
w_arm: list=[0.45,1.35],
|
||||
xs: str = 'strip',
|
||||
arm_sine_width: bool=False,
|
||||
L_mmi: list = [10],
|
||||
w_mmi: list = [5,5],
|
||||
|
||||
mmi_sine_width: bool=False,
|
||||
|
||||
sharp_patch: bool=True,
|
||||
show_pins: bool = False,
|
||||
|
||||
res: float = 0.01,
|
||||
N_out: int = 3,
|
||||
N_in: int = 1,
|
||||
Dp_out: float = 1.5,
|
||||
Dp_in: float = 1.5,
|
||||
) -> None:
|
||||
|
||||
self.name = name
|
||||
if (self.name==None):
|
||||
self.instantiate = False
|
||||
else :
|
||||
self.instantiate = True
|
||||
|
||||
self.L_arm = L_arm
|
||||
self.xs = xs
|
||||
self.w_arm = w_arm
|
||||
self.arm_sine_width = arm_sine_width
|
||||
self.L_mmi = L_mmi
|
||||
self.w_mmi = w_mmi
|
||||
self.res = res
|
||||
self.N_out = N_out
|
||||
self.N_in = N_in
|
||||
self.Dp_out = Dp_out
|
||||
self.Dp_in = Dp_in
|
||||
self.mmi_sine_width = mmi_sine_width
|
||||
|
||||
self.cell = self.generate_gds(sharp_patch=sharp_patch,show_pins=show_pins)
|
||||
|
||||
self.L = np.sum(self.L_arm)*2+np.sum(self.L_mmi)
|
||||
|
||||
def generate_gds(self,sharp_patch,show_pins):
|
||||
|
||||
with nd.Cell(instantiate=self.instantiate,name=self.name) as C:
|
||||
L = 0
|
||||
Lsg = []
|
||||
Wsg = []
|
||||
for idx in range(0,len(self.L_arm)):
|
||||
n_points = round(self.L_arm[idx]/self.res)+1
|
||||
L_sect = np.linspace(L,L+self.L_arm[idx],n_points)
|
||||
Lsg = np.r_[Lsg,L_sect]
|
||||
if (self.arm_sine_width):
|
||||
dw = self.w_arm[idx+1]-self.w_arm[idx]
|
||||
w_sect = -np.cos(L_sect/self.L_arm[idx]*pi)*dw + (self.w_arm[idx+1]-self.w_arm[idx])/2
|
||||
else:
|
||||
w_sect = np.linspace(self.w_arm[idx],self.w_arm[idx+1],n_points)
|
||||
Wsg = np.r_[Wsg,w_sect]
|
||||
|
||||
L = L + self.L_arm[idx]
|
||||
|
||||
with nd.Cell(instantiate=False) as Arm:
|
||||
for layers,growx,growy,acc in nd.layeriter(xs=self.xs):
|
||||
(a1,b1), (a2,b2),c1,c2 = growx
|
||||
|
||||
vtx_y = np.r_[Wsg*a1+b1, np.flip(Wsg,0)*a2+b2]
|
||||
vtx_x = np.r_[Lsg, np.flip(Lsg,0)]
|
||||
vtx = np.c_[vtx_x,vtx_y]
|
||||
_my_polygon(layer_wg=layers,vtx=vtx).put(0,0,0)
|
||||
|
||||
|
||||
nd.Pin(name='a1',width=Wsg[0]).put(0,0,180)
|
||||
nd.Pin(name='b1',width=Wsg[-1]).put(L,0,0)
|
||||
|
||||
""" For central MMI """
|
||||
L_mmi = 0
|
||||
Lsg_mmi = []
|
||||
Wsg_mmi = []
|
||||
for idx in range(0,len(self.L_mmi)):
|
||||
n_points = round(self.L_mmi[idx]/self.res)+1
|
||||
L_sect = np.linspace(L_mmi,L_mmi+self.L_mmi[idx],n_points)
|
||||
Lsg_mmi = np.r_[Lsg_mmi,L_sect]
|
||||
if (self.arm_sine_width):
|
||||
dw = self.w_mmi[idx+1]-self.w_mmi[idx]
|
||||
w_sect = -np.cos(L_sect/self.L_mmi[idx]*pi)*dw + (self.w_mmi[idx+1]-self.w_mmi[idx])/2
|
||||
else:
|
||||
w_sect = np.linspace(self.w_mmi[idx],self.w_mmi[idx+1],n_points)
|
||||
Wsg_mmi = np.r_[Wsg_mmi,w_sect]
|
||||
|
||||
L_mmi = L_mmi + self.L_mmi[idx]
|
||||
|
||||
with nd.Cell(instantiate=False) as MMI:
|
||||
for layers,growx,growy,acc in nd.layeriter(xs=self.xs):
|
||||
(a1,b1), (a2,b2),c1,c2 = growx
|
||||
|
||||
vtx_y = np.r_[Wsg_mmi*a1+b1, np.flip(Wsg_mmi,0)*a2+b2]
|
||||
vtx_x = np.r_[Lsg_mmi, np.flip(Lsg_mmi,0)]
|
||||
vtx = np.c_[vtx_x,vtx_y]
|
||||
if (b1==0 and b2==0):
|
||||
_my_polygon(layer_wg=layers,vtx=vtx).put(0,0,0)
|
||||
else :
|
||||
w = max(Wsg_mmi)+b1*2
|
||||
L = max(Lsg_mmi)+b1*2
|
||||
nd.strt(length=L,layer=layers,width=w).put(-b1,0,0)
|
||||
|
||||
nd.Pin(name='a1',width=Wsg_mmi[0]).put(0,0,180)
|
||||
nd.Pin(name='b1',width=Wsg_mmi[-1]).put(L_mmi,0,0)
|
||||
|
||||
for idx_in in range(0,self.N_in):
|
||||
Arm_inst = Arm.put('b1',0,self.Dp_in*(-idx_in+(self.N_in-1)/2),180)
|
||||
nd.Pin(name='a'+str(round(idx_in+1)),pin=Arm_inst.pin['a1']).put()
|
||||
|
||||
for idx_in in range(0,self.N_out):
|
||||
Arm_inst = Arm.put('b1',L_mmi,self.Dp_out*(-idx_in+(self.N_out-1)/2),0)
|
||||
nd.Pin(name='b'+str(round(idx_in+1)),pin=Arm_inst.pin['a1']).put()
|
||||
MMI.put('a1',0,0,0)
|
||||
|
||||
if (show_pins):
|
||||
nd.put_stub()
|
||||
|
||||
return C
|
||||
|
||||
def generate_test_gds(self,gc,dX_gc2gc,dY_gc2gc,R_bend=10,Xout_offset=50):
|
||||
if (isinstance(gc,nd.Cell)):
|
||||
gc_cell =gc
|
||||
elif (hasattr(gc,'cell')):
|
||||
gc_cell = gc.cell
|
||||
else :
|
||||
raise Exception("ERROR: In <mxpic::passive::ADC_STD_2x2::generate_test_gds>, <gc> is not recongized as a cell")
|
||||
|
||||
with nd.Cell(instantiate=False) as C:
|
||||
|
||||
INST = self.cell.put(-self.L/2,0,0)
|
||||
pic_strip = Route(width=self.w_arm[0],radius=R_bend,xs=self.xs)
|
||||
for idx_in in range(0,self.N_in):
|
||||
GC = gc_cell.put('g1',-dX_gc2gc/2,dY_gc2gc*(-idx_in + (self.N_in-1)/2),180)
|
||||
pic_strip.sbend_p2p(pin1=GC.pin['g1'],pin2=INST.pin['a'+str(idx_in+1)],Lstart=dX_gc2gc/10).put()
|
||||
|
||||
for idx_in in range(0,self.N_out):
|
||||
toggle = np.mod(idx_in,2)-0.5
|
||||
GC = gc_cell.put('g1', dX_gc2gc/2+Xout_offset*toggle,dY_gc2gc*(-idx_in + (self.N_out-1)/2),0)
|
||||
pic_strip.sbend_p2p(pin1=GC.pin['g1'],pin2=INST.pin['b'+str(idx_in+1)],Lstart=dX_gc2gc/10).put()
|
||||
|
||||
return C
|
||||
|
||||
|
||||
class MMI_STD(MMI_ML):
|
||||
def __init__(self,
|
||||
name: Optional[str]=None,
|
||||
N_out: int=3,
|
||||
N_in: int=1,
|
||||
L_arm: int=10,
|
||||
w_wg: float=0.45,
|
||||
w_port: float = 1.2,
|
||||
xs: str='strip',
|
||||
L_mmi: int=10,
|
||||
w_mmi: float=5,
|
||||
sharp_patch: bool=True,
|
||||
show_pins: bool=False,
|
||||
Dp_out: float=1.5,
|
||||
Dp_in: float=1.5) -> None:
|
||||
""" Standard MMI with multiple input and output
|
||||
|
||||
Args:
|
||||
L_arm (int, optional): _description_. Defaults to 10.
|
||||
w_wg (float, optional): _description_. Defaults to 0.45.
|
||||
w_port (float, optional): _description_. Defaults to 1.2.
|
||||
xs (str, optional): _description_. Defaults to 'strip'.
|
||||
arm_sine_width (bool, optional): _description_. Defaults to False.
|
||||
L_mmi (int, optional): _description_. Defaults to 10.
|
||||
w_mmi (int, optional): _description_. Defaults to 5.
|
||||
mmi_sine_width (bool, optional): _description_. Defaults to False.
|
||||
sharp_patch (bool, optional): _description_. Defaults to True.
|
||||
show_pins (bool, optional): _description_. Defaults to False.
|
||||
res (float, optional): _description_. Defaults to 0.01.
|
||||
N_out (int, optional): _description_. Defaults to 3.
|
||||
N_in (int, optional): _description_. Defaults to 1.
|
||||
Dp_out (float, optional): _description_. Defaults to 1.5.
|
||||
Dp_in (float, optional): _description_. Defaults to 1.5.
|
||||
"""
|
||||
super().__init__(name=name,
|
||||
L_arm=[L_arm],
|
||||
w_arm=[w_wg,w_port],
|
||||
xs=xs,
|
||||
arm_sine_width=False,
|
||||
L_mmi=[L_mmi],
|
||||
w_mmi=[w_mmi,w_mmi],
|
||||
mmi_sine_width=False,
|
||||
sharp_patch=sharp_patch,
|
||||
show_pins=show_pins,
|
||||
res=min([L_mmi,L_arm]), ## taper resolution
|
||||
N_out=N_out,
|
||||
N_in=N_in,
|
||||
Dp_out=Dp_out,
|
||||
Dp_in=Dp_in)
|
||||
@@ -0,0 +1,295 @@
|
||||
from typing import Any, Optional
|
||||
import nazca as nd
|
||||
import numpy as np
|
||||
from .couplers import ring_bus_wg
|
||||
|
||||
from .taper import taper_xs2xs
|
||||
|
||||
from ...structures import Racetrack,Clothoid,circle,Elipse_dual
|
||||
from . import ring_bus_wg
|
||||
from ...electronics import Vias
|
||||
import nazca.interconnects as IC
|
||||
from ...basic import __cell_arg__
|
||||
|
||||
class Route(IC.Interconnect):
|
||||
pass
|
||||
# from ...routing import *
|
||||
|
||||
|
||||
|
||||
class RacetrackResonator:
|
||||
def __init__(self,
|
||||
|
||||
R0: Any,
|
||||
w0: float,
|
||||
R1: Any,
|
||||
w1: float,
|
||||
dLy: float,
|
||||
dLx: float,
|
||||
name: Optional[str] = None,
|
||||
xs: str='strip',
|
||||
gap1: float = 0.2,
|
||||
gap2: float = 0.2,
|
||||
w1_bus: float = 0.45,
|
||||
w2_bus: float = 0.45,
|
||||
R1_cp: Any = None,
|
||||
R2_cp: Any = None,
|
||||
A1_cp: int = 0,
|
||||
A2_cp: int = 0,
|
||||
w_wg: float = 0.45,
|
||||
R1_att: float = 20,
|
||||
R2_att: float = 20,
|
||||
R2_att_min: float= 10,
|
||||
R1_att_min: float = 10,
|
||||
A1_att: float = 30,
|
||||
A2_att: float = 20,
|
||||
Ltp_bus: int = 10,
|
||||
dL_p2p: Optional[float] = None,
|
||||
L_tilt: int = 10,
|
||||
sharp_patch: bool=True,
|
||||
cell_xs_transition: Any=None,
|
||||
Euler_trasition: bool = False,
|
||||
res: float = 0.01, ## default to 1nm accurancy
|
||||
show_pins: bool=False
|
||||
) -> None:
|
||||
self.name = name
|
||||
if (name==None):
|
||||
self.instantiate = False
|
||||
else:
|
||||
self.instantiate = True
|
||||
|
||||
self.R0 = R0
|
||||
self.R1 = R1
|
||||
self.w0 = w0
|
||||
self.w1 = w1
|
||||
self.dLy = dLy
|
||||
self.dLx = dLx
|
||||
self.gap1 = gap1
|
||||
self.gap2 = gap2
|
||||
self.w1_bus = w1_bus
|
||||
self.w2_bus = w2_bus
|
||||
|
||||
if (R1_cp==None):
|
||||
self.R1_cp = self.R0+self.w0/2+self.gap1+self.w1_bus/2
|
||||
else :
|
||||
self.R1_cp = R1_cp
|
||||
|
||||
if (R2_cp==None):
|
||||
self.R2_cp = self.R0+self.w0/2+self.gap2+self.w2_bus/2
|
||||
else :
|
||||
self.R2_cp = R2_cp
|
||||
|
||||
|
||||
self.A1_cp = A1_cp
|
||||
self.A2_cp = A2_cp
|
||||
self.w_wg = w_wg
|
||||
self.R1_att = R1_att
|
||||
self.R2_att = R2_att
|
||||
self.R2_att_min = R2_att_min
|
||||
self.R1_att_min = R1_att_min
|
||||
self.A1_att = A1_att
|
||||
self.A2_att = A2_att
|
||||
self.Ltp_bus = Ltp_bus
|
||||
self.dL_p2p = dL_p2p
|
||||
self.L_tilt = L_tilt
|
||||
self.xs = xs
|
||||
|
||||
self.Euler_trasition = Euler_trasition
|
||||
self.res = res
|
||||
|
||||
self.cell = self.generate_gds(sharp_patch=sharp_patch,show_pins=show_pins)
|
||||
|
||||
def generate_gds(self,sharp_patch=True,show_pins=False):
|
||||
|
||||
with nd.Cell(name=self.name,instantiate=self.instantiate) as C:
|
||||
|
||||
|
||||
bend_cell = Clothoid(R=[self.R1,self.R0],A=[0,90],width_type='sine',
|
||||
w=[self.w0,self.w1],
|
||||
xs=self.xs,
|
||||
dL_wg=self.res)
|
||||
|
||||
self.RCK = Racetrack(bend_cell=bend_cell,
|
||||
xs=self.xs,
|
||||
w=self.w1,
|
||||
dLx=self.dLx,
|
||||
dLy=self.dLy,
|
||||
res=self.res)
|
||||
|
||||
RCK_INSTR = self.RCK.cell.put(0,0,0)
|
||||
|
||||
|
||||
bus = ring_bus_wg(xs=self.xs,
|
||||
R_cp=self.R1_cp,
|
||||
w_bus=self.w1_bus,
|
||||
dAc=self.A1_cp,
|
||||
wg_Ltp=self.Ltp_bus,
|
||||
dA_trans=self.A1_att,
|
||||
R_max_trans=self.R1_att,
|
||||
R_max_anti=self.R1_att,
|
||||
R_min_anti=self.R1_att_min,
|
||||
dL_p2p=self.dL_p2p,
|
||||
sharp_patch=sharp_patch,
|
||||
dL_trans=self.L_tilt,
|
||||
euler_anti_bend=self.Euler_trasition,
|
||||
euler_transistion=self.Euler_trasition)
|
||||
|
||||
self.cell_bus = bus.cell
|
||||
bus_instr = bus.cell.put(0,-self.dLy/2-bend_cell.sz[1]-self.w0/2-self.w1_bus/2-self.gap1,0)
|
||||
bus_instr.raise_pins(['a1','b1'],['a1','b1'])
|
||||
|
||||
if (self.w2_bus > 0):
|
||||
bus_instr = bus.cell.put(0, self.dLy/2+bend_cell.sz[1]+self.w0/2+self.w2_bus/2+self.gap2,0,flip=1)
|
||||
bus_instr.raise_pins(['a1','b1'],['a2','b2'])
|
||||
|
||||
return C
|
||||
|
||||
|
||||
|
||||
class Racetrack_STD_Allpass(RacetrackResonator):
|
||||
def __init__(self,
|
||||
r_rck: float, w_rck: float,
|
||||
dLy: float,
|
||||
name: Optional[str]=None, xs: str='strip',
|
||||
gap: float=0.2,
|
||||
w_bus: float=0.45,
|
||||
A_cp: int=0,
|
||||
w_wg: float=0.45,
|
||||
Ltp_bus: int=10, dL_p2p: Optional[float]=None, L_tilt: int=0,
|
||||
Ratt: int = 10,
|
||||
w_ht: float=0,
|
||||
w_mt: float=10,
|
||||
via_h2m: Any=None,
|
||||
xs_ht: str = "heater",
|
||||
xs_mt: str = "metal",
|
||||
sharp_patch: bool=True, cell_xs_transition: Any=None, res: float=0.01, show_pins: bool=False) -> None:
|
||||
if (w_ht>0):
|
||||
name_pic = None
|
||||
else:
|
||||
name_pic = name
|
||||
super().__init__(R0=r_rck, w0=w_rck,
|
||||
R1=r_rck, w1=w_rck,
|
||||
dLy=dLy, dLx=0,
|
||||
name=name_pic, xs=xs,
|
||||
gap1=gap, gap2=0,
|
||||
w1_bus=w_bus, w2_bus=0,
|
||||
R1_cp=None, R2_cp=None,
|
||||
A1_cp=A_cp, A2_cp=0,
|
||||
w_wg=w_wg,
|
||||
R1_att=Ratt, R2_att=Ratt,
|
||||
R2_att_min=Ratt, R1_att_min=Ratt,
|
||||
A1_att=A_cp/2, A2_att=A_cp/2, Ltp_bus=Ltp_bus,
|
||||
dL_p2p=dL_p2p, L_tilt=L_tilt, sharp_patch=sharp_patch,
|
||||
cell_xs_transition=cell_xs_transition, Euler_trasition=False, res=res, show_pins=show_pins)
|
||||
|
||||
self.w_rck = w_rck
|
||||
self.r_rck = r_rck
|
||||
|
||||
self.w_bus = w_bus
|
||||
self.gap = gap
|
||||
|
||||
self.xs_ht = xs_ht
|
||||
self.xs_mt = xs_mt
|
||||
|
||||
self.w_ht = w_ht
|
||||
self.w_mt = w_mt
|
||||
self.via_h2m = via_h2m
|
||||
|
||||
if (self.w_ht > 0):
|
||||
self.cell_pic = self.cell
|
||||
|
||||
with nd.Cell(instantiate=True, name=name) as C:
|
||||
INSTR = self.cell.put()
|
||||
INSTR.raise_pins()
|
||||
|
||||
eic_cell = self.generate_eic_gds().put()
|
||||
eic_cell.raise_pins(["ep1","en1"],["ep1","en1"])
|
||||
|
||||
self.cell = C
|
||||
|
||||
def generate_eic_gds(self, sharp_patch=True, show_pins=False):
|
||||
with nd.Cell(instantiate=False) as C:
|
||||
|
||||
HT_L = nd.strt(length=self.dLy/2,width=self.w_ht,xs=self.xs_ht).put(self.RCK.sz[0]/2,0,90)
|
||||
HT = nd.bend(radius=self.r_rck,width=self.w_ht,xs=self.xs_ht,angle=180).put()
|
||||
HT_R = nd.strt(length=self.dLy/2,width=self.w_ht,xs=self.xs_ht).put(-self.RCK.sz[0]/2,0,90)
|
||||
|
||||
if (self.via_h2m is None):
|
||||
self.VIA = Vias(xs=None,xs_l1=self.xs_ht,xs_l2=self.xs_mt,sz=self.w_ht,area=self.w_mt,spacing=0)
|
||||
else :
|
||||
self.VIA = __cell_arg__(arg=self.via_h2m,arg_name="via_h2m",func_name="Racetrack_STD_Allpass::generate_eic_gds")
|
||||
|
||||
HT_L = nd.strt(length=self.w_ht/2,width=self.w_ht,xs=self.xs_ht).put(self.RCK.sz[0]/2,0,-90)
|
||||
HT_R = nd.strt(length=self.w_ht/2,width=self.w_ht,xs=self.xs_ht).put(-self.RCK.sz[0]/2,0,-90)
|
||||
|
||||
VIAL = self.VIA.put(HT_L.pin['b0'])
|
||||
VIAR = self.VIA.put(HT_R.pin['b0'],flip=1)
|
||||
|
||||
VIAL.raise_pins(['b0'],["en1"])
|
||||
VIAR.raise_pins(['b0'],["ep1"])
|
||||
|
||||
return C
|
||||
|
||||
|
||||
class Racetrack_MM_Allpass(RacetrackResonator):
|
||||
def __init__(self,
|
||||
r1_rck: float, w1_rck: float,
|
||||
r0_rck: float, w0_rck: float,
|
||||
dLy: float,
|
||||
name: Optional[str]=None, xs: str='strip',
|
||||
gap: float=0.2,
|
||||
w_bus: float=0.45,
|
||||
A_cp: int=0,
|
||||
w_wg: float=0.45,
|
||||
R_att: int=50,
|
||||
R_att_min: int=10,
|
||||
A_att: int = 15,
|
||||
Ltp_bus: int=10, dL_p2p: Optional[float]=None,
|
||||
sharp_patch: bool=True, cell_xs_transition: Any=None, res: float=0.01, show_pins: bool=False) -> None:
|
||||
super().__init__(R0=r0_rck, w0=w0_rck,
|
||||
R1=r1_rck, w1=w1_rck,
|
||||
dLy=dLy, dLx=0,
|
||||
name=name, xs=xs,
|
||||
gap1=gap, gap2=0,
|
||||
w1_bus=w_bus, w2_bus=0,
|
||||
R1_cp=None, R2_cp=None,
|
||||
A1_cp=A_cp, A2_cp=0,
|
||||
w_wg=w_wg,
|
||||
R1_att=R_att, R2_att=R_att,
|
||||
R2_att_min=R_att_min, R1_att_min=R_att_min,
|
||||
A1_att=A_att, A2_att=A_att,
|
||||
Ltp_bus=Ltp_bus,
|
||||
dL_p2p=dL_p2p, L_tilt=0, sharp_patch=sharp_patch,
|
||||
cell_xs_transition=cell_xs_transition, Euler_trasition=True, res=res, show_pins=show_pins)
|
||||
|
||||
|
||||
class Racetrack_MM_Adddrop(RacetrackResonator):
|
||||
def __init__(self,
|
||||
r1_rck: float, w1_rck: float,
|
||||
r0_rck: float, w0_rck: float,
|
||||
dLy: float,
|
||||
name: Optional[str]=None, xs: str='strip',
|
||||
gap: float=0.2,
|
||||
w_bus: float=0.45,
|
||||
A_cp: int=0,
|
||||
w_wg: float=0.45,
|
||||
R_att: int=50,
|
||||
R_att_min: int=10,
|
||||
A_att: int = 15,
|
||||
Ltp_bus: int=10, dL_p2p: Optional[float]=None,
|
||||
sharp_patch: bool=True, cell_xs_transition: Any=None, res: float=0.01, show_pins: bool=False) -> None:
|
||||
super().__init__(R0=r0_rck, w0=w0_rck,
|
||||
R1=r1_rck, w1=w1_rck,
|
||||
dLy=dLy, dLx=0,
|
||||
name=name, xs=xs,
|
||||
gap1=gap, gap2=gap,
|
||||
w1_bus=w_bus, w2_bus=w_bus,
|
||||
R1_cp=None, R2_cp=None,
|
||||
A1_cp=A_cp, A2_cp=A_cp,
|
||||
w_wg=w_wg,
|
||||
R1_att=R_att, R2_att=R_att,
|
||||
R2_att_min=R_att_min, R1_att_min=R_att_min,
|
||||
A1_att=A_att, A2_att=A_att,
|
||||
Ltp_bus=Ltp_bus,
|
||||
dL_p2p=dL_p2p, L_tilt=0, sharp_patch=sharp_patch,
|
||||
cell_xs_transition=cell_xs_transition, Euler_trasition=True, res=res, show_pins=show_pins)
|
||||
@@ -0,0 +1,293 @@
|
||||
from typing import Any, Optional
|
||||
import nazca as nd
|
||||
import numpy as np
|
||||
from .couplers import ring_bus_wg
|
||||
|
||||
from .taper import taper_xs2xs
|
||||
|
||||
from ...structures import *
|
||||
# import nazca.interconnects as IC
|
||||
from ...routing import Route
|
||||
|
||||
from ...basic import __cell_arg__
|
||||
|
||||
# class Route(IC.Interconnect):
|
||||
# pass
|
||||
# from ...routing import *
|
||||
|
||||
|
||||
""" 2023.03.19 REVISED """
|
||||
""" NOTE: n_points will not be used in any future class, res will be the accurancy parameter """
|
||||
|
||||
class AED_ring :
|
||||
def __init__(self,
|
||||
name: Optional[str]=None,
|
||||
ORx: float = 10,
|
||||
ORy: float = 10,
|
||||
IRx: float = 10-0.45,
|
||||
IRy: float = 10-0.65,
|
||||
gap1: float = 0.2,
|
||||
gap2: float = 0.2,
|
||||
w1_bus: float = 0.45,
|
||||
w2_bus: float = 0.45,
|
||||
R1_cp: Any = None,
|
||||
R2_cp: Any = None,
|
||||
A1_cp: int = 0,
|
||||
A2_cp: int = 0,
|
||||
offset_X: float=0,
|
||||
offset_Y: float=0,
|
||||
|
||||
w_wg: float = 0.45,
|
||||
R1_att: float = 20,
|
||||
R2_att: float = 20,
|
||||
R2_att_min: float= 10,
|
||||
R1_att_min: float = 10,
|
||||
A1_att: float = 30,
|
||||
A2_att: float = 20,
|
||||
|
||||
Ltp_bus: int = 10,
|
||||
dL_p2p: Optional[float] = None,
|
||||
L_tilt: int = 10,
|
||||
xs: str='strip',
|
||||
sharp_patch: bool=True,
|
||||
cell_xs_transition: Any=None,
|
||||
Euler_trasition: bool = False,
|
||||
res: float = 0.01, ## default to 1nm accurancy
|
||||
show_pins: bool=False) -> None:
|
||||
|
||||
|
||||
self.name = name
|
||||
if (self.name==None):
|
||||
self.instantiate = False
|
||||
else :
|
||||
self.instantiate = True
|
||||
|
||||
self.ORx = ORx
|
||||
self.ORy = ORy
|
||||
self.IRx = IRx
|
||||
self.IRy = IRy
|
||||
self.gap1 = gap1
|
||||
self.gap2 = gap2
|
||||
self.w1_bus = w1_bus
|
||||
self.w2_bus = w2_bus
|
||||
self.R1_cp = R1_cp
|
||||
self.R2_cp = R2_cp
|
||||
self.A1_cp = A1_cp
|
||||
self.A2_cp = A2_cp
|
||||
|
||||
self.offset_X = offset_X
|
||||
self.offset_Y = offset_Y
|
||||
|
||||
self.L_tilt = L_tilt
|
||||
|
||||
self.w_wg = w_wg
|
||||
self.R1_att = R1_att
|
||||
self.R1_att_min = R1_att_min
|
||||
self.A1_att = A1_att
|
||||
self.R2_att = R2_att
|
||||
self.R2_att_min = R2_att_min
|
||||
self.A2_att = A2_att
|
||||
|
||||
self.Ltp_bus = Ltp_bus
|
||||
self.dL_p2p = dL_p2p
|
||||
|
||||
self.xs = xs
|
||||
self.sharp_patch = sharp_patch
|
||||
self.show_pins = show_pins
|
||||
self.cell_xs_transition = cell_xs_transition
|
||||
self.Euler_trasition = Euler_trasition
|
||||
# self.n_points = n_points
|
||||
self.res = res
|
||||
|
||||
self.cell = self.generate_pic_gds(sharp_patch=sharp_patch,show_pins=show_pins)
|
||||
self.pic_cell = self.cell
|
||||
|
||||
def generate_pic_gds(self,sharp_patch,show_pins):
|
||||
with nd.Cell(instantiate=self.instantiate,name=self.name) as C:
|
||||
|
||||
Rb = min([self.ORx+self.IRx,self.ORy+self.IRy])/2
|
||||
Ra = max([self.ORx+self.IRx,self.ORy+self.IRy])/2
|
||||
_L_perimeter_ = 2*pi*Rb + 4*(Ra-Rb)
|
||||
|
||||
|
||||
""" Placing the central ring """
|
||||
Elipse_dual(xs=self.xs,ORy=self.ORy,ORx=self.ORx,IRx=self.IRx,IRy=self.IRy,
|
||||
offset_X=self.offset_X,offset_Y=self.offset_Y,sharp_patch=sharp_patch,
|
||||
# n_points=self.n_points,
|
||||
res=self.res).cell.put(0,0,0)
|
||||
|
||||
""" FATAL ERROR: REVISED IN 2022.09.19 """
|
||||
if (self.R1_cp == None):
|
||||
# self.R1_cp = self.r_ring+self.gap1+self.w1_bus/1+self.w_ring/2
|
||||
self.R1_cp = self.ORy+self.gap1+self.w1_bus/2
|
||||
|
||||
if (self.xs!='strip'):
|
||||
end_patch = True
|
||||
else :
|
||||
end_patch = False
|
||||
|
||||
bus_class = ring_bus_wg(xs=self.xs, R_cp=self.R1_cp,
|
||||
w_bus=self.w1_bus,bend_DC=True, w_wg=self.w_wg, dAc=self.A1_cp,
|
||||
euler_anti_bend=self.Euler_trasition,euler_transistion=self.Euler_trasition,
|
||||
|
||||
R_max_trans=self.R1_att,dA_trans=self.A1_att,dL_trans=self.L_tilt,
|
||||
R_max_anti=self.R1_att,R_min_anti=self.R1_att_min,
|
||||
|
||||
sharp_patch=self.sharp_patch,show_pins=show_pins,
|
||||
wg_Ltp=self.Ltp_bus,w_trans=self.w1_bus,
|
||||
dL_p2p=self.dL_p2p,
|
||||
res=self.res, ## Added in 2023.1.3, to simplfy the points in coupler
|
||||
end_patch=end_patch
|
||||
# ).cell.put(0,-(self.r_ring+self.gap1+self.w1_bus/1+self.w_ring/2))
|
||||
)
|
||||
bus = bus_class.cell
|
||||
self.bus = bus_class
|
||||
self.cell_bus = bus
|
||||
bus = bus.put(0,-(self.ORy+self.gap1+self.w1_bus/2))
|
||||
|
||||
""" xs transition refreshed in 2023.05.16 """
|
||||
if (self.cell_xs_transition!=None):
|
||||
if (isinstance(self.cell_xs_transition,nd.Cell)):
|
||||
cell_trans = self.cell_xs_transition
|
||||
elif(hasattr(self.cell_xs_transition,'cell')):
|
||||
cell_trans = self.cell_xs_transition.cell
|
||||
|
||||
temp = cell_trans.put(bus.pin['a1'])
|
||||
nd.Pin(name='a1',pin=temp.pin['b0']).put()
|
||||
temp = cell_trans.put(bus.pin['b1'])
|
||||
nd.Pin(name='b1',pin=temp.pin['b0']).put()
|
||||
else:
|
||||
nd.Pin(name='a1',pin=bus.pin['a1']).put()
|
||||
nd.Pin(name='b1',pin=bus.pin['b1']).put()
|
||||
|
||||
if show_pins:
|
||||
nd.put_stub()
|
||||
|
||||
## The upper coupling bus ##
|
||||
if self.w2_bus >0:
|
||||
if (self.R2_cp == None):
|
||||
self.R2_cp = self.ORy+self.gap2+self.w2_bus/2
|
||||
|
||||
bus = ring_bus_wg(xs=self.xs, R_cp=self.R2_cp,
|
||||
w_bus=self.w2_bus,bend_DC=True, w_wg=self.w_wg, dAc=self.A2_cp,
|
||||
euler_anti_bend=self.Euler_trasition,euler_transistion=self.Euler_trasition,
|
||||
|
||||
R_max_trans=self.R2_att,dA_trans=self.A2_att,dL_trans=self.L_tilt,
|
||||
R_max_anti=self.R2_att,R_min_anti=self.R2_att_min,
|
||||
|
||||
sharp_patch=self.sharp_patch,show_pins=show_pins,
|
||||
wg_Ltp=self.Ltp_bus,w_trans=self.w2_bus,
|
||||
dL_p2p=self.dL_p2p,
|
||||
res=self.res, ## Added in 2023.1.3, to simplfy the points in coupler
|
||||
end_patch=end_patch
|
||||
|
||||
).cell.put(0,(self.ORy+self.gap2+self.w2_bus/2),flip=1)
|
||||
|
||||
if (self.cell_xs_transition!=None):
|
||||
if (isinstance(self.cell_xs_transition,nd.Cell)):
|
||||
cell_trans = self.cell_xs_transition
|
||||
elif(hasattr(self.cell_xs_transition,'cell')):
|
||||
cell_trans = self.cell_xs_transition.cell
|
||||
|
||||
temp = cell_trans.put(bus.pin['a1'])
|
||||
nd.Pin(name='a2',pin=temp.pin['b0']).put()
|
||||
temp = cell_trans.put(bus.pin['b1'])
|
||||
nd.Pin(name='b2',pin=temp.pin['b0']).put()
|
||||
else:
|
||||
nd.Pin(name='a2',pin=bus.pin['a1']).put()
|
||||
nd.Pin(name='b2',pin=bus.pin['b1']).put()
|
||||
|
||||
if show_pins:
|
||||
nd.put_stub()
|
||||
|
||||
return C
|
||||
|
||||
def generate_test_gds(self,GC,dX_gc2gc,dY_gc2gc,offset=0,w_wg=0.45,w_term=0.18,R_bend=10,xs='strip',cell_attribute=None):
|
||||
|
||||
if (cell_attribute==None):
|
||||
test_cell = self.cell
|
||||
else :
|
||||
test_cell = getattr(self,cell_attribute)
|
||||
|
||||
if (self.name!=None):
|
||||
test_c_name = self.name + "_test"
|
||||
else :
|
||||
test_c_name = "AED_ring_test_NO"
|
||||
|
||||
with nd.Cell(name=test_c_name,instantiate=True) as C:
|
||||
|
||||
GC = __cell_arg__(arg=GC,arg_name="GC",func_name="AED_rings::generate_test_gds")
|
||||
GC1 = GC.put('g1',0,0,180)
|
||||
GC2 = GC.put('g1',dX_gc2gc,0,0)
|
||||
|
||||
pic_strip = Route(width=w_wg,radius=R_bend,xs=xs,MM_route=False)
|
||||
|
||||
if (self.w2_bus>0):
|
||||
dX_c = abs(test_cell.pin['a1'].y - test_cell.pin['a2'].y)
|
||||
dY_c = abs(test_cell.pin['a1'].x - test_cell.pin['a2'].x)
|
||||
INSTR = test_cell.put('a1',GC1.pin['g1'].x + dX_gc2gc/2-dX_c/2-R_bend-offset,GC1.pin['g1'].y-R_bend-1,-90,flip=0)
|
||||
pic_strip.bend_p2p(pin1=INSTR.pin['a1'],pin2=GC1.pin['g1']).put()
|
||||
pic_strip.bend_p2p(pin1=INSTR.pin['a2'],pin2=GC2.pin['g1']).put()
|
||||
|
||||
GC3 = GC.put('g1',GC2.pin['g1'].x,GC2.pin['g1'].y-dY_gc2gc,0)
|
||||
pic_strip.bend_p2p(pin1=INSTR.pin['b1'],pin2=GC3.pin['g1']).put()
|
||||
|
||||
pic_strip.bend_route(pin=INSTR.pin['b2'],length1=0.5,length2=0.5).put()
|
||||
pic_strip.taper(width2=w_term,length=15).put()
|
||||
|
||||
else:
|
||||
dX_c = abs(test_cell.pin['a1'].x - test_cell.pin['b1'].x)
|
||||
INSTR = test_cell.put('a1',GC1.pin['g1'].x + dX_gc2gc/2-dX_c/2-R_bend-offset,GC1.pin['g1'].y,0,flip=0)
|
||||
pic_strip.strt_p2p(pin1=INSTR.pin['a1'],pin2=GC1.pin['g1']).put()
|
||||
pic_strip.strt_p2p(pin1=INSTR.pin['b1'],pin2=GC2.pin['g1']).put()
|
||||
|
||||
INSTR.raise_pins()
|
||||
nd.Pin(name='a0').put(0,0,180)
|
||||
nd.Pin(name='b0').put(0,0,0)
|
||||
return C
|
||||
|
||||
class STD_PIC_Rings(AED_ring):
|
||||
def __init__(self,
|
||||
name: Optional[str] = None,
|
||||
r_ring: float=10,
|
||||
w_ring: float=10,
|
||||
|
||||
gap1: float=0.2,
|
||||
gap2: float=0.2,
|
||||
w1_bus: float=0.45,
|
||||
w2_bus: float=0,
|
||||
R1_cp: Any=None,
|
||||
R2_cp: Any=None,
|
||||
A1_cp: int=0,
|
||||
A2_cp: int=0,
|
||||
offset_X: float=0,
|
||||
offset_Y: float=0,
|
||||
w_wg: float=0.45,
|
||||
R1_att: float = 20,
|
||||
R2_att: float = 20,
|
||||
R2_att_min: float = 10,
|
||||
R1_att_min: float = 10,
|
||||
A1_att: float = 30,
|
||||
A2_att: float = 20,
|
||||
Ltp_bus: int=10,
|
||||
dL_p2p: Optional[float]=None,
|
||||
L_tilt: int=10,
|
||||
xs: str='strip',
|
||||
sharp_patch: bool=True,
|
||||
cell_xs_transition: Any=None,
|
||||
Euler_trasition: bool=False,
|
||||
res: float = 0.001,
|
||||
show_pins: bool=False) -> None:
|
||||
|
||||
ORx = r_ring+w_ring/2
|
||||
ORy = r_ring+w_ring/2
|
||||
IRx = r_ring-w_ring/2
|
||||
IRy = r_ring-w_ring/2
|
||||
|
||||
|
||||
super().__init__(name,
|
||||
ORx,
|
||||
ORy,
|
||||
IRx, IRy, gap1, gap2, w1_bus, w2_bus, R1_cp, R2_cp, A1_cp, A2_cp, offset_X, offset_Y, w_wg,
|
||||
R1_att, R2_att, R2_att_min, R1_att_min, A1_att, A2_att, Ltp_bus, dL_p2p, L_tilt, xs, sharp_patch, cell_xs_transition, Euler_trasition, res=res,
|
||||
show_pins=show_pins)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,295 @@
|
||||
import nazca as nd
|
||||
import numpy as np
|
||||
import math
|
||||
from ...routing import Route
|
||||
|
||||
from ...structures import *
|
||||
from ....technologies import *
|
||||
|
||||
import pandas as pd
|
||||
from ...structures import _my_polygon
|
||||
|
||||
""" NEW Classes :: Transistion area of rib to strip, to minize the loss """
|
||||
class transition:
|
||||
def __init__(self,
|
||||
layer_FETCH: str="STRIP_TRE",
|
||||
layer_METCH: str="RIB_TRE",
|
||||
w_rib: float=1.1,
|
||||
dw_tolerance: float = 0.2,
|
||||
w_grow_rib: float=2,
|
||||
w_grow_strip: float=2,
|
||||
Ltp1: int=15,
|
||||
Ltp2: int=10,
|
||||
Ltrans: int=5,
|
||||
L_port: int=2,
|
||||
show_pins: bool=False,
|
||||
) -> None:
|
||||
|
||||
with nd.Cell(instantiate=False) as C:
|
||||
""" Placing taper for rib etching"""
|
||||
dLx = np.array([0,L_port+Ltp1+Ltrans+Ltp2,Ltp2])
|
||||
vtx_x = np.cumsum(dLx)
|
||||
vtx_x = np.r_[vtx_x,vtx_x[-1],0]
|
||||
vtx_y = np.array([w_rib/2,w_rib/2,w_rib/2+dw_tolerance,w_rib/2+w_grow_rib+w_grow_strip,w_rib/2+w_grow_rib+w_grow_strip])
|
||||
vtx = np.c_[vtx_x,vtx_y]
|
||||
_my_polygon(layer_wg=layer_METCH,vtx=vtx).put(0,0,0)
|
||||
|
||||
vtx_y = -vtx_y
|
||||
vtx = np.c_[vtx_x,vtx_y]
|
||||
_my_polygon(layer_wg=layer_METCH,vtx=vtx).put(0,0,0)
|
||||
|
||||
""" Placing taper for rib etching"""
|
||||
dLx = np.array([0,L_port,Ltp1,Ltp2,Ltrans+Ltp2+L_port])
|
||||
vtx_x = np.cumsum(dLx)
|
||||
vtx_x = np.r_[vtx_x,vtx_x[-1],0]
|
||||
vtx_y = np.array([w_rib/2+w_grow_rib,w_rib/2+w_grow_rib,w_rib/2+dw_tolerance,w_rib/2,w_rib/2,w_rib/2+w_grow_rib+w_grow_strip,w_rib/2+w_grow_rib+w_grow_strip])
|
||||
vtx = np.c_[vtx_x,vtx_y]
|
||||
_my_polygon(layer_wg=layer_FETCH,vtx=vtx).put(0,0,0)
|
||||
|
||||
vtx_y = -vtx_y
|
||||
vtx = np.c_[vtx_x,vtx_y]
|
||||
_my_polygon(layer_wg=layer_FETCH,vtx=vtx).put(0,0,0)
|
||||
|
||||
nd.Pin(name='a0',width=w_rib).put(0,0,180)
|
||||
nd.Pin(name='b0',width=w_rib).put(L_port*2+Ltrans+Ltp1+Ltp2*2,0,0)
|
||||
|
||||
if (show_pins):
|
||||
nd.put_stub()
|
||||
|
||||
self.cell = C
|
||||
|
||||
class taper_xs2xs:
|
||||
def __init__ (self,
|
||||
xs_1:str='rib',
|
||||
xs_2:str='strip',
|
||||
L_taper:float=10,
|
||||
w_1:float=0.45,
|
||||
w_2:float=0.45,
|
||||
L_port:float = 0) -> None:
|
||||
"""_summary_
|
||||
|
||||
Args:
|
||||
xs_1 (str, optional): fisrt xsection. Defaults to 'rib'.
|
||||
xs_2 (str, optional): second xsection. Defaults to 'strip'.
|
||||
L_taper (float, optional): length of the xsection taper. Defaults to 10.
|
||||
w_1 (float, optional): first xsection width. Defaults to 0.45.
|
||||
w_2 (float, optional): second xsection width. Defaults to 0.45.
|
||||
L_port (float, optional): length attached to the end. Defaults to 0.
|
||||
|
||||
Raises:
|
||||
Exception: No xsection input found
|
||||
"""
|
||||
|
||||
|
||||
with nd.Cell(instantiate=False) as C:
|
||||
|
||||
xs_1_layer_list = []
|
||||
xs_2_layer_list = []
|
||||
growx_1_list = []
|
||||
growx_2_list = []
|
||||
|
||||
## input guard
|
||||
try:
|
||||
nd.get_xsection(xs_1)
|
||||
except:
|
||||
raise Exception("ERROR: in <mxpic.passive.pic.taper.taper_xs2xs> No xsection ==",xs_1,"== were found")
|
||||
|
||||
try:
|
||||
nd.get_xsection(xs_2)
|
||||
except:
|
||||
raise Exception("ERROR: in <mxpic.passive.pic.taper.taper_xs2xs> No xsection ==",xs_2,"== were found")
|
||||
|
||||
|
||||
for layers_1,growx,growy,acc in nd.layeriter(xs=xs_1):
|
||||
xs_1_layer_list = xs_1_layer_list + [layers_1]
|
||||
growx_1_list = growx_1_list + [growx]
|
||||
|
||||
|
||||
for layers_2,growx,growy,acc in nd.layeriter(xs=xs_2):
|
||||
|
||||
xs_2_layer_list = xs_2_layer_list + [layers_2]
|
||||
growx_2_list = growx_2_list + [growx]
|
||||
|
||||
|
||||
for layers_1 in xs_1_layer_list:
|
||||
if (layers_1 in xs_2_layer_list):
|
||||
## same layer
|
||||
(a1_1,b1_1), (a2_1,b2_1),c1,c2 = growx_1_list[xs_1_layer_list.index(layers_1)]
|
||||
(a1_2,b1_2), (a2_2,b2_2),c1,c2 = growx_2_list[xs_2_layer_list.index(layers_1)]
|
||||
w1 = w_1*(a1_1-a2_1) + (b1_1-b2_1)
|
||||
w2 = w_2*(a1_2-a2_2) + (b1_2-b2_2)
|
||||
nd.taper(length=L_taper,width1=w1,width2=w2,layer=layers_1).put(0,0,0)
|
||||
else :
|
||||
if (layers_1.find('COR')!=-1):
|
||||
(a1_1,b1_1), (a2_1,b2_1),c1,c2 = growx_1_list[xs_1_layer_list.index(layers_1)]
|
||||
w1 = w_1*(a1_1-a2_1) + (b1_1-b2_1)
|
||||
w2 = w_2
|
||||
nd.taper(length=L_taper,width1=w1,width2=w2,layer=layers_1).put(0,0,0)
|
||||
else :
|
||||
(a1_1,b1_1), (a2_1,b2_1),c1,c2 = growx_1_list[xs_1_layer_list.index(layers_1)]
|
||||
w1 = w_1*(a1_1-a2_1) + (b1_1-b2_1)
|
||||
w2 = w_2*(a1_1-a2_1) + (b1_1-b2_1)
|
||||
nd.taper(length=L_taper,width1=w1,width2=w2,layer=layers_1).put(0,0,0)
|
||||
|
||||
for layers_2 in xs_2_layer_list:
|
||||
if (layers_2 not in xs_1_layer_list):
|
||||
if (layers_2.find('COR')!=-1):
|
||||
(a1_2,b1_2), (a2_2,b2_2),c1,c2 = growx_2_list[xs_2_layer_list.index(layers_2)]
|
||||
w1 = w_1
|
||||
w2 = w_2*(a1_2-a2_2) + (b1_2-b2_2)
|
||||
nd.taper(length=L_taper,width1=w1,width2=w2,layer=layers_2).put(0,0,0)
|
||||
|
||||
else :
|
||||
(a1_1,b1_1), (a2_1,b2_1),c1,c2 = growx_2_list[xs_2_layer_list.index(layers_2)]
|
||||
w1 = w_1*(a1_1-a2_1) + (b1_1-b2_1) ## Revised 2022.12.06, HGL
|
||||
w2 = w_2*(a1_1-a2_1) + (b1_1-b2_1)
|
||||
nd.taper(length=L_taper,width1=w1,width2=w2,layer=layers_2).put(0,0,0)
|
||||
|
||||
nd.strt(length=L_port,xs=xs_1,width=w_1).put(0,0,180)
|
||||
nd.strt(length=L_port,xs=xs_2,width=w_2).put(L_taper,0,0)
|
||||
|
||||
nd.Pin(name='a0',width=w_1).put(-L_port,0,180)
|
||||
nd.Pin(name='a1',width=w_1).put(-L_port,0,180)
|
||||
nd.Pin(name='b0',width=w_2).put(L_taper+L_port,0,0)
|
||||
nd.Pin(name='b1',width=w_2).put(L_taper+L_port,0,0)
|
||||
|
||||
self.cell = C
|
||||
|
||||
class PSR:
|
||||
"""
|
||||
Polarization Splitter & rotator
|
||||
"""
|
||||
def __init__ (self,
|
||||
|
||||
name : str="PSR_unit",
|
||||
xs :str='rib',
|
||||
layer_u: str=None, ## override xs_u
|
||||
layer_d: str=None, ## override xs_d
|
||||
w: list=[0.45,0.45,0.55,1.2,1.2],
|
||||
Lt_rib: list=[10,30,30,10],
|
||||
ws: list=[0.45,2,1.2],
|
||||
Lt_slab: list=[40,40],
|
||||
shape:str='sine',
|
||||
L_port:float = 5,
|
||||
res:float=0.01) -> None:
|
||||
|
||||
if (name==None):
|
||||
instantiate = False
|
||||
else :
|
||||
instantiate = True
|
||||
|
||||
try:
|
||||
nd.get_xsection(xs)
|
||||
except:
|
||||
raise Exception("ERROR: In <mxpic::passive::taper>, xs=",xs," is not defined in the tapeout")
|
||||
|
||||
|
||||
|
||||
if (len(w)!=len(Lt_rib)+1):
|
||||
print("WARNING: In <mxpic::passive::taper>, rib area width section do not match with taper section")
|
||||
return 0
|
||||
|
||||
if (len(w)!=len(Lt_rib)+1):
|
||||
print("WARNING: In <mxpic::passive::taper>, slab area width section do not match with taper section")
|
||||
return 0
|
||||
|
||||
w = np.array(w).tolist()
|
||||
ws = np.array(ws).tolist()
|
||||
Lt_rib = np.array(Lt_rib).tolist()
|
||||
Lt_slab = np.array(Lt_slab).tolist()
|
||||
|
||||
self.w = w
|
||||
self.ws = ws
|
||||
self.Lt_rib = Lt_rib
|
||||
self.Lt_slab = Lt_slab
|
||||
|
||||
## defining the shape of the PSR
|
||||
if (shape=='sine'):
|
||||
wu_final = []
|
||||
Lu_final = []
|
||||
for _idx_ in range(0,len(Lt_rib)):
|
||||
|
||||
Lt_seg = np.linspace(0,Lt_rib[_idx_],int(Lt_rib[_idx_]/res)+1)
|
||||
wu_temp = (w[_idx_] + w[_idx_+1])/2 + (w[_idx_] - w[_idx_+1])/2*np.cos(Lt_seg/Lt_rib[_idx_]*pi)
|
||||
if (_idx_>=0):
|
||||
Lt_seg = Lt_seg + np.sum(Lt_rib[0:_idx_])
|
||||
|
||||
wu_final = np.r_[wu_final,wu_temp]
|
||||
Lu_final = np.r_[Lu_final,Lt_seg]
|
||||
|
||||
wd_final = []
|
||||
Ld_final = []
|
||||
|
||||
for _idx_ in range(0,len(Lt_slab)):
|
||||
Lt_seg = np.linspace(0,Lt_slab[_idx_],int(Lt_slab[_idx_]/res)+1)
|
||||
wd_temp = (ws[_idx_] + ws[_idx_+1])/2 + (ws[_idx_] - ws[_idx_+1])/2*np.cos(Lt_seg/Lt_slab[_idx_]*pi)
|
||||
if (_idx_>0):
|
||||
Lt_seg = Lt_seg + np.sum(Lt_slab[0:_idx_])
|
||||
|
||||
wd_final = np.r_[wd_final,wd_temp]
|
||||
Ld_final = np.r_[Ld_final,Lt_seg]
|
||||
|
||||
elif(shape=='linear'):
|
||||
|
||||
wd_final = np.array(ws)
|
||||
Ld_final = np.array(Lt_slab)
|
||||
wu_final = np.array(w)
|
||||
Lu_final = np.array(Lt_rib)
|
||||
Lu_final = np.r_[0,np.cumsum(Lu_final)]
|
||||
Ld_final = np.r_[0,np.cumsum(Ld_final)] ## FATAL ERROR CORRECTED: 2023.1.31
|
||||
|
||||
# print(wd_final,wu_final)
|
||||
# print(Ld_final,Lu_final)
|
||||
|
||||
else:
|
||||
wd_final = np.array(ws)
|
||||
Ld_final = np.array(Lt_slab)
|
||||
wu_final = np.array(w)
|
||||
Lu_final = np.array(Lt_rib)
|
||||
Lu_final = np.r_[0,np.cumsum(Lu_final)]
|
||||
Ld_final = np.r_[0,np.cumsum(Ld_final)]
|
||||
|
||||
Lu_vtx = np.r_[Lu_final,np.flip(np.array(Lu_final),0)]
|
||||
Ld_vtx = np.r_[Ld_final,np.flip(np.array(Ld_final),0)]
|
||||
wu_vtx = np.r_[wu_final/2,np.flip(np.array(-wu_final/2),0)]
|
||||
wd_vtx = np.r_[wd_final/2,np.flip(np.array(-wd_final/2),0)]
|
||||
|
||||
with nd.Cell(instantiate=instantiate,name=name) as C:
|
||||
|
||||
if (layer_u!=None and layer_d!=None):
|
||||
vtx = np.c_[Lu_vtx,wu_vtx]
|
||||
_my_polygon(layer_u,vtx).put(0,0,0)
|
||||
vtx = np.c_[Ld_vtx,wd_vtx]
|
||||
_my_polygon(layer_d,vtx).put(0,0,0)
|
||||
|
||||
else :
|
||||
for layers,growx,growy,acc in nd.layeriter(xs=xs):
|
||||
(a1,b1), (a2,b2),c1,c2 = growx
|
||||
if (b1==0 and b2==0 and layers.find("COR")!=-1):
|
||||
wu_temp = np.r_[wu_final/2,np.flip(np.array(-wu_final/2),0)]
|
||||
vtx = np.c_[Lu_vtx,wu_temp]
|
||||
_my_polygon(layers,vtx).put(0,0,0)
|
||||
w0=wu_final[0]
|
||||
w1=wu_final[-1]
|
||||
|
||||
elif (layers.find("COR")!=-1):
|
||||
wd_temp = np.r_[wd_final/2,np.flip(np.array(-wd_final/2),0)]
|
||||
vtx = np.c_[Ld_vtx,wd_temp]
|
||||
_my_polygon(layers,vtx).put(0,0,0)
|
||||
w0=wd_final[0]
|
||||
w1=wd_final[-1]
|
||||
else :
|
||||
wd_temp = np.r_[(wd_final*(a1-a2)+(b1-b2))/2,np.flip(np.array(-(wd_final*(a1-a2)+(b1-b2))/2),0)]
|
||||
vtx = np.c_[Ld_vtx,wd_temp]
|
||||
_my_polygon(layers,vtx).put(0,0,0)
|
||||
w0=(wd_final[0]*(a1-a2)+(b1-b2))
|
||||
w1=(wd_final[-1]*(a1-a2)+(b1-b2))
|
||||
|
||||
nd.strt(width=w0,length=L_port,layer=layers).put(0,0,180)
|
||||
nd.strt(width=w1,length=L_port,layer=layers).put(sum(Lt_rib),0,0)
|
||||
|
||||
nd.Pin(name='a1',width=w[0]).put(-L_port,0,180)
|
||||
nd.Pin(name='b1',width=w[-1]).put(sum(Lt_rib)+L_port,0,0)
|
||||
self.cell = C
|
||||
|
||||
|
||||
Reference in New Issue
Block a user