Update to github version
This commit is contained in:
@@ -76,20 +76,10 @@ class EC_dual_layer_px3():
|
||||
layer_dum_exl_be:str=None,
|
||||
angle_tile: float = 8,
|
||||
R_bend: float = 50,
|
||||
sample_build = False,
|
||||
):
|
||||
""""""
|
||||
|
||||
""" This is the instruction for building a sample """
|
||||
if (sample_build):
|
||||
name = "EC_dual_layer_px3"
|
||||
w_in = 0.8
|
||||
L_in = 15
|
||||
Ltp1 = 50
|
||||
Ltp2 = 150
|
||||
Ltp3 = 450
|
||||
|
||||
|
||||
""" This is the instruction for building a sample """
|
||||
self.name = name
|
||||
if (self.name is None): self.instantiate = False
|
||||
else: self.instantiate = True
|
||||
|
||||
@@ -3,4 +3,5 @@ from .EC_dual_layer_px3 import *
|
||||
from .directional_couplers import *
|
||||
from .beam_splitters import *
|
||||
from .multimode_interferometers import *
|
||||
from .spiral import *
|
||||
from .spiral import *
|
||||
from .grating_couplers import *
|
||||
@@ -452,7 +452,7 @@ class ADC_STD_2x2:
|
||||
_dX_ = abs(pin_a1.x)
|
||||
|
||||
else :
|
||||
Ltp = np.max([_dX_-5,np.abs(self.wu0+err-self.wu_in)/np.tan(self.tp_angle/180*pi)])
|
||||
Ltp = np.max([-5,np.abs(self.wu0+err-self.wu_in)/np.tan(self.tp_angle/180*pi)])
|
||||
Ltp = int(Ltp*20)*0.05 ## keep it in integer
|
||||
temp = nd.strt(xs=self.xs,length=5,width=self.wu0+err).put(0,vtx_upper_y[0]/2+vtx_upper_y[-1]/2,180,flip=0)
|
||||
pin_a1 = nd.taper(xs=self.xs,length=Ltp,width1=self.wu0+err,width2=self.wu_in).put().pin['b0']
|
||||
|
||||
@@ -394,172 +394,6 @@ class Grating_2D_Hole() :
|
||||
)
|
||||
return ic
|
||||
|
||||
class Grating_2D_Hole_4Rec() :
|
||||
"""
|
||||
Assemble four identical 2D hole gratings into a rectangular array.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
grating_unit : Grating_2D_Hole
|
||||
Pre-built grating instance supplying the unit cell.
|
||||
mode_radius : float, optional
|
||||
Radius of the target circular fiber mode in microns (default is 8).
|
||||
cell_name : str or None, optional
|
||||
Nazca cell name suffix; ``None`` uses "TwoD_Grating" (default is None).
|
||||
show_pins : bool, optional
|
||||
Draw Nazca stub markers on exported IO pins (default is False).
|
||||
"""
|
||||
def __init__(self, grating_unit, mode_radius=8, cell_name=None, show_pins=False) -> None:
|
||||
self.gt_2D_class = grating_unit
|
||||
self.cell_unit = grating_unit.cell
|
||||
self.mode_radius = mode_radius
|
||||
|
||||
# Calculate the field center location
|
||||
# radius = np.sqrt(2)/2 * (
|
||||
# self.mode_radius + np.sqrt(2)/2*(grating_unit.w_gt/2-grating_unit.l_field_center) -
|
||||
# np.sqrt(np.power(self.mode_radius, 2) - 1/2*np.power(grating_unit.w_gt/2-grating_unit.l_field_center, 2))
|
||||
# )
|
||||
# print("---------------------"+str(radius)+"------------------------------")
|
||||
l_field_center = grating_unit.l_field_center
|
||||
w_gt = grating_unit.w_gt
|
||||
x0 = (
|
||||
2*(w_gt/2-l_field_center)-np.sqrt(
|
||||
8*mode_radius**2 - 4 * (w_gt/2 - l_field_center)**2
|
||||
)
|
||||
) / 4
|
||||
self.field_center = (
|
||||
x0 + mode_radius*np.cos(np.pi/4),
|
||||
x0 + mode_radius*np.cos(np.pi/4),
|
||||
180
|
||||
)
|
||||
self.cell_unit._put_pin(name='g0', connect=self.field_center)
|
||||
|
||||
self.show_pins = show_pins
|
||||
self.cell_name = cell_name
|
||||
self.cell = self.generate_gds()
|
||||
|
||||
def generate_gds(self) :
|
||||
if self.cell_name is not None : self.cell_name = "TwoD_Grating_" + self.cell_name
|
||||
else : self.cell_name = "TwoD_Grating"
|
||||
with nd.Cell(name=self.cell_name, instantiate=False) as ic :
|
||||
gt_1 = self.cell_unit.put(
|
||||
'g0', self.mode_radius*np.cos(np.pi/4), self.mode_radius*np.sin(np.pi/4)
|
||||
)
|
||||
gt_2 = self.cell_unit.put(
|
||||
'g0', self.mode_radius*np.cos(np.pi/4), -self.mode_radius*np.sin(np.pi/4), flip=True
|
||||
)
|
||||
gt_3 = self.cell_unit.put(
|
||||
'g0', -self.mode_radius*np.cos(np.pi/4), -self.mode_radius*np.sin(np.pi/4), flip=True, flop=True
|
||||
)
|
||||
gt_4 = self.cell_unit.put(
|
||||
'g0', -self.mode_radius*np.cos(np.pi/4), self.mode_radius*np.sin(np.pi/4), flip=False, flop=True
|
||||
)
|
||||
'''Put OPEN and PATH region if necessary.'''
|
||||
if nd.get_layer(layer="GC_OPEN") == "GC_OPEN" :
|
||||
nd.Polygon(
|
||||
points=nd.geom.circle(radius=self.mode_radius+20, N=int(np.floor((self.mode_radius+20)/0.1))),
|
||||
layer="GC_OPEN"
|
||||
).put(0,0)
|
||||
if nd.get_layer(layer="STRIP_CLD") == "STRIP_CLD" :
|
||||
nd.Polygon(
|
||||
points=nd.geom.circle(radius=self.mode_radius+10, N=int(np.floor((self.mode_radius+20)/0.1))),
|
||||
layer="STRIP_CLD"
|
||||
).put(0,0)
|
||||
''' Put Pins '''
|
||||
nd.Pin(name='g1').put(gt_1.pin['g1'])
|
||||
nd.Pin(name='g2').put(gt_1.pin['g2'])
|
||||
nd.Pin(name='g3').put(gt_2.pin['g1'])
|
||||
nd.Pin(name='g4').put(gt_2.pin['g2'])
|
||||
nd.Pin(name='g5').put(gt_3.pin['g1'])
|
||||
nd.Pin(name='g6').put(gt_3.pin['g2'])
|
||||
nd.Pin(name='g7').put(gt_4.pin['g1'])
|
||||
nd.Pin(name='g8').put(gt_4.pin['g2'])
|
||||
nd.Pin(name='a0').put(gt_1.pin['g1'].x, 0, 0)
|
||||
if self.show_pins :
|
||||
nd.put_stub()
|
||||
return ic
|
||||
|
||||
class Grating_2D_Hole_3Rec() :
|
||||
"""
|
||||
Assemble three identical 2D hole gratings in triangular symmetry.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
grating_unit : Grating_2D_Hole
|
||||
Source grating instance providing the layout cell.
|
||||
mode_radius : float, optional
|
||||
Radius of the circumscribed fiber mode in microns (default is 6.5).
|
||||
cell_name : str or None, optional
|
||||
Custom Nazca cell name suffix (default is None).
|
||||
show_pins : bool, optional
|
||||
Draw Nazca stub markers on exported IO pins (default is False).
|
||||
"""
|
||||
def __init__(self, grating_unit, mode_radius=6.5, cell_name=None, show_pins=False) -> None:
|
||||
self.gt_2D_class = grating_unit
|
||||
self.cell_unit = grating_unit.cell
|
||||
self.mode_radius = mode_radius
|
||||
self.cell_name = cell_name
|
||||
|
||||
# Calculate the field center location
|
||||
radius = np.sqrt(2)/2 * (
|
||||
self.mode_radius + np.sqrt(2)/2*(grating_unit.w_gt/2-grating_unit.l_field_center) -
|
||||
np.sqrt(np.power(self.mode_radius, 2) - 1/2*np.power(grating_unit.w_gt/2-grating_unit.l_field_center, 2))
|
||||
)
|
||||
self.field_center = (
|
||||
radius*np.cos(np.pi/4),
|
||||
radius*np.cos(np.pi/4),
|
||||
45
|
||||
)
|
||||
self.cell_unit._put_pin(name='g0', connect=self.field_center)
|
||||
self.show_pins = show_pins
|
||||
|
||||
self.cell = self.generate_gds()
|
||||
|
||||
def generate_gds(self) :
|
||||
if self.cell_name is not None : self.cell_name = "TwoD_Grating_" + self.cell_name
|
||||
else : self.cell_name = "TwoD_Grating"
|
||||
with nd.Cell(name=self.cell_name, instantiate=False) as ic :
|
||||
rotation_angle = 2*np.pi/3*0
|
||||
gt_1 = self.cell_unit.put(
|
||||
'g0',
|
||||
self.mode_radius*np.cos(rotation_angle), self.mode_radius*np.sin(rotation_angle),
|
||||
180 + rotation_angle*180/np.pi
|
||||
)
|
||||
rotation_angle = 2*np.pi/3*1
|
||||
gt_2 = self.cell_unit.put(
|
||||
'g0',
|
||||
self.mode_radius*np.cos(rotation_angle), self.mode_radius*np.sin(rotation_angle),
|
||||
180 + rotation_angle*180/np.pi
|
||||
)
|
||||
rotation_angle = 2*np.pi/3*2
|
||||
gt_3 = self.cell_unit.put(
|
||||
'g0',
|
||||
self.mode_radius*np.cos(rotation_angle), self.mode_radius*np.sin(rotation_angle),
|
||||
180 + rotation_angle*180/np.pi
|
||||
)
|
||||
'''Put OPEN and PATH region if necessary.'''
|
||||
if nd.get_layer(layer="GC_OPEN") == "GC_OPEN" :
|
||||
nd.Polygon(
|
||||
points=nd.geom.circle(radius=self.mode_radius+20, N=int(np.floor((self.mode_radius+20)/0.1))),
|
||||
layer="GC_OPEN"
|
||||
).put(0,0)
|
||||
if nd.get_layer(layer="STRIP_CLD") == "STRIP_CLD" :
|
||||
nd.Polygon(
|
||||
points=nd.geom.circle(radius=self.mode_radius+10, N=int(np.floor((self.mode_radius+20)/0.1))),
|
||||
layer="STRIP_CLD"
|
||||
).put(0,0)
|
||||
'''Put pins'''
|
||||
nd.Pin(name='g1').put(gt_1.pin['g1'])
|
||||
nd.Pin(name='g2').put(gt_1.pin['g2'])
|
||||
nd.Pin(name='g3').put(gt_2.pin['g1'])
|
||||
nd.Pin(name='g4').put(gt_2.pin['g2'])
|
||||
nd.Pin(name='g5').put(gt_3.pin['g1'])
|
||||
nd.Pin(name='g6').put(gt_3.pin['g2'])
|
||||
if self.show_pins :
|
||||
nd.put_stub()
|
||||
return ic
|
||||
|
||||
|
||||
""" Renamed for simplification in 2023.04.02 """
|
||||
class GC_STD_2D:
|
||||
"""
|
||||
@@ -632,14 +466,14 @@ class GC_STD_2D:
|
||||
Py:float=0.57,
|
||||
num_x:float=25,
|
||||
num_y:float=25,
|
||||
Lx_taper:float = 50,
|
||||
Ly_taper:float = 0,
|
||||
Lx_end:float = 1,
|
||||
Ly_end:float = 1,
|
||||
Lx_taper:float = 50.0,
|
||||
Ly_taper:float = 0.0,
|
||||
Lx_end:float = 1.0,
|
||||
Ly_end:float = 1.0,
|
||||
Lx_side:float = 0.5,
|
||||
Ly_side:float = 0.5,
|
||||
Lx_port:float=5,
|
||||
Ly_port:float=5,
|
||||
Lx_port:float=5.0,
|
||||
Ly_port:float=5.0,
|
||||
w_wg:float=0.5,
|
||||
show_pins:bool=False,
|
||||
P_AR: float = 0.6,
|
||||
@@ -926,18 +760,18 @@ class GC_STD_1D:
|
||||
w_wg : float = 0.5,
|
||||
etch_type :str = 'FETCH',
|
||||
xs_open :str=None,
|
||||
L_taper :float = 10,
|
||||
L_end :float = 2,
|
||||
A_taper :float = 30,
|
||||
L_taper :float = 10.0,
|
||||
L_end :float = 2.0,
|
||||
A_taper :float = 30.0,
|
||||
Period :float = 0.5,
|
||||
eta_etch :float = 0.5,
|
||||
num :float = 20, ### note, when Period and eta is defined as list, this is not usefull
|
||||
num :int = 20, ### note, when Period and eta is defined as list, this is not usefull
|
||||
sector_gc :bool =True,
|
||||
show_pins=False,
|
||||
L_tail = 2,
|
||||
# n_points = 64,
|
||||
P_AR: float = 1, ### adding anti reflection pitches
|
||||
L_AR: float = 2,
|
||||
P_AR: float = 1.0, ### adding anti reflection pitches
|
||||
L_AR: float = 2.0,
|
||||
):
|
||||
|
||||
self.name = name
|
||||
@@ -1276,3 +1110,133 @@ class FA:
|
||||
nd.put_stub(pinsize=3)
|
||||
self.cell = C
|
||||
|
||||
class GC_SiN_Si_Dual_Layer:
|
||||
def __init__(self,
|
||||
name:str=None,
|
||||
w_teeth_SiN:'list|float' = 0.5,
|
||||
gap_teeth_SiN:'list|float' = 0.5,
|
||||
w_teeth_Si:'list|float' = 0.5,
|
||||
gap_teeth_Si:'list|float' = 0.5,
|
||||
ori_teeth_offset:float = 5.0,
|
||||
n_teeth_Si:float=30,
|
||||
n_teeth_SiN:float=30,
|
||||
A_gc_taper:float=25.0,
|
||||
R_teeth_ori_SiN:float=40.0,
|
||||
R_teeth_ori_Si:float=40.0,
|
||||
L_end_Si:float=0.2,
|
||||
L_end_SiN:float=5.0,
|
||||
|
||||
w_port : float = 0.9,
|
||||
|
||||
A_anti_rfl:float = 4.0,
|
||||
layer_SiN_slab:str=None,
|
||||
layer_Si_slab:str=None,
|
||||
layer_Si_teeth:str=None,
|
||||
layer_SiN_teeth:str=None,
|
||||
layer_SiN_etch:str=None,
|
||||
layer_Si_etch:str=None,
|
||||
layer_ox_open:str=None,
|
||||
):
|
||||
|
||||
self.name = name
|
||||
self.w_teeth_SiN = w_teeth_SiN
|
||||
self.gap_teeth_SiN = gap_teeth_SiN
|
||||
self.w_teeth_Si = w_teeth_Si
|
||||
self.gap_teeth_Si = gap_teeth_Si
|
||||
self.ori_teeth_offset = ori_teeth_offset
|
||||
|
||||
self.n_teeth_SiN = n_teeth_SiN
|
||||
self.n_teeth_Si = n_teeth_Si
|
||||
|
||||
self.A_gc_taper = A_gc_taper
|
||||
|
||||
self.w_port = w_port
|
||||
|
||||
self.L_end_Si = L_end_Si
|
||||
self.L_end_SiN = L_end_SiN
|
||||
|
||||
self.A_anti_rfl = A_anti_rfl
|
||||
|
||||
self.R_teeth_ori_SiN = R_teeth_ori_SiN
|
||||
self.R_teeth_ori_Si = R_teeth_ori_Si
|
||||
|
||||
self.layer_SiN_slab = layer_SiN_slab
|
||||
self.layer_Si_slab = layer_Si_slab
|
||||
self.layer_Si_teeth = layer_Si_teeth
|
||||
self.layer_SiN_teeth = layer_SiN_teeth
|
||||
self.layer_SiN_etch = layer_SiN_etch
|
||||
self.layer_Si_etch = layer_Si_etch
|
||||
self.layer_ox_open = layer_ox_open
|
||||
|
||||
self.cell = self.generate_gds()
|
||||
|
||||
def generate_gds(self):
|
||||
""" creating instance cell or not """
|
||||
if (self.name is None) : self.instantiate = False
|
||||
else : self.instantiate = True
|
||||
|
||||
""" """
|
||||
if (isinstance(self.w_teeth_SiN,list) or isinstance(self.w_teeth_SiN,np.ndarray)):
|
||||
n_teeth_SiN = len(self.w_teeth_SiN)
|
||||
elif (isinstance(self.w_teeth_SiN,float)):
|
||||
n_teeth_SiN = self.n_teeth_SiN
|
||||
w_teeth_SiN = [w_teeth_SiN]*n_teeth_SiN
|
||||
|
||||
""" """
|
||||
if (isinstance(self.w_teeth_Si,list) or isinstance(self.w_teeth_Si,np.ndarray)):
|
||||
n_teeth_Si = len(self.w_teeth_Si)
|
||||
elif (isinstance(self.w_teeth_Si,float)):
|
||||
n_teeth_Si = self.n_teeth_Si
|
||||
w_teeth_Si = [w_teeth_Si]*n_teeth_Si
|
||||
|
||||
with nd.Cell(instantiate=self.instantiate, name=self.name) as C:
|
||||
|
||||
""" Creating SiN layer grating """
|
||||
## whole area where the grating area covered
|
||||
L_gc = self.R_teeth_ori_SiN + self.L_end_SiN + sum(self.w_teeth_SiN) + sum(self.gap_teeth_SiN)
|
||||
|
||||
w_box_gc = L_gc*np.sin(self.A_gc_taper/2*np.pi/180)*2
|
||||
L_box_gc = L_gc*np.cos(self.A_gc_taper/2*np.pi/180)
|
||||
x_slab = [0,L_box_gc,L_gc+w_box_gc*np.sin(self.A_anti_rfl*np.pi/180),L_gc,L_box_gc,0]
|
||||
y_slab = [self.w_port/2,w_box_gc/2,w_box_gc/2,-w_box_gc/2,-w_box_gc/2,-self.w_port/2]
|
||||
|
||||
_my_polygon(layer_wg=self.layer_SiN_slab,vtx=np.c_[x_slab,y_slab]).put(0,0,0)
|
||||
|
||||
# circle(radius=self.R_teeth_ori_SiN/2,angle=self.A_gc_taper,layer=self.layer_SiN_slab,
|
||||
# width=self.R_teeth_ori_SiN).cell.put(0,0,-self.A_gc_taper/2)
|
||||
|
||||
A_etch_ext = 4
|
||||
## Placing teeth
|
||||
r_in = self.R_teeth_ori_SiN
|
||||
for idxT in range(0,n_teeth_SiN):
|
||||
r_out = r_in + self.gap_teeth_SiN[idxT]
|
||||
|
||||
circle(radius=(r_out+r_in)/2,angle=self.A_gc_taper+A_etch_ext,layer=self.layer_SiN_etch,
|
||||
width=self.gap_teeth_Si[idxT]).cell.put(0,0,-self.A_gc_taper/2-A_etch_ext/2)
|
||||
|
||||
r_in = r_out + self.w_teeth_SiN[idxT]
|
||||
|
||||
""" Creating Si layer grating """
|
||||
|
||||
w_Si_slab = sum(self.w_teeth_Si)+sum(self.gap_teeth_Si)
|
||||
R_Si_slab = self.R_teeth_ori_Si+w_Si_slab/2
|
||||
circle(radius=R_Si_slab,angle=self.A_gc_taper,layer=self.layer_Si_slab,
|
||||
width=w_Si_slab).cell.put(0,0,-self.A_gc_taper/2)
|
||||
|
||||
## Placing teeth
|
||||
r_in = self.R_teeth_ori_Si
|
||||
for idxT in range(0,n_teeth_Si):
|
||||
r_out = r_in + self.gap_teeth_Si[idxT]
|
||||
|
||||
if (self.layer_Si_etch is not None):
|
||||
circle(radius=(r_out+r_in)/2,angle=self.A_gc_taper+A_etch_ext,layer=self.layer_Si_etch,
|
||||
width=self.gap_teeth_Si[idxT]).cell.put(0,0,-self.A_gc_taper/2-A_etch_ext/2)
|
||||
elif (self.layer_Si_teeth is not None):
|
||||
circle(radius=r_out+(self.w_teeth_Si[idxT])/2,angle=self.A_gc_taper,layer=self.layer_Si_teeth,
|
||||
width=self.w_teeth_Si[idxT]).cell.put(0,0,-self.A_gc_taper/2)
|
||||
|
||||
r_in = r_out + self.w_teeth_Si[idxT]
|
||||
|
||||
return C
|
||||
|
||||
|
||||
|
||||
@@ -565,7 +565,11 @@ class spiral_rectangle:
|
||||
print("WARNING: In <mxpic::passive::spiral>, Dmin too small")
|
||||
D_port = self.Dmin - bend_sz[1]*2
|
||||
|
||||
with nd.Cell(instantiate=True,name="wg_mid_cell"+self.name) as wg_mid_cell:
|
||||
if (self.name is None):
|
||||
wg_mid_name = None
|
||||
else:
|
||||
wg_mid_name = "wg_mid_cell"+self.name
|
||||
with nd.Cell(instantiate=self.instantiate,name=wg_mid_name) as wg_mid_cell:
|
||||
|
||||
wg = self.__strt_with_taper__(length=self.Lmin-bend_sz[0]*2-bend_sz[0],width2=self.width,width1=bend_cell.pin['a0'].
|
||||
width,xs=self.xs,Ltp=self.Ltp).put(-self.Lmin/2+bend_sz[0]*2+bend_sz[0],0,0,flip=1)
|
||||
|
||||
Reference in New Issue
Block a user