Files
mxpic_forge/mxpic/components/primitives/passive/crows.py
T

1431 lines
58 KiB
Python

from typing import Any, Optional
from turtle import ht
import nazca as nd
import numpy as np
import nazca.interconnects as IC
from ...geometry import *
from ...routing import *
from .unit import *
from .rings import *
from ..pic import *
from ...electronics import Vias
from ...basic import __array_convert__,__list_convert__,__xs_exist__,__cell_arg__
class STD_CROW_V:
"""
STD CROW V primitive component.
This component builds the STD CROW V layout cell.
Parameters
----------
ring : Any
Ring cell or component used by this composite.
bus : Any
Bus waveguide cell or component used by this composite.
w_bus : float or list
Width parameter in microns.
w_ring : float or list
Width parameter in microns.
sz_ring : float or list
Value for the sz_ring parameter.
sz_bus : float or list
Value for the sz_bus parameter.
name : str, optional
Unique identifier for the device cell. Default is None.
gap_crows : float or list, optional
Spacing or gap parameter in microns. Default is [0.4].
gap_cp : float or list, optional
Spacing or gap parameter in microns. Default is [0.45, 0.45].
w_heater : float or list, optional
Width parameter in microns. Default is 0.
xs_heater : str, optional
Layer or cross-section name used by the device. Default is 'heater'.
connected : bool, optional
Value for the connected parameter. Default is True.
w_metal : float, optional
Width parameter in microns. Default is 8.
xs_metal : str, optional
Layer or cross-section name used by the device. Default is 'metal'.
via_h2m : Any, optional
Via definition used between heater and metal layers. Default is None.
isl : Any, optional
Isolation-trench definition used by the electrical layout. Default is None.
ht_shift : int, optional
Value for the ht_shift parameter. Default is 0.
A_ht : int, optional
Angle parameter in degrees. Default is 45.
ISL_LEFT : bool, optional
Value for the ISL_LEFT parameter. Default is True.
ISL_RIGHT : bool, optional
Value for the ISL_RIGHT parameter. Default is True.
show_pins : bool, optional
Whether to draw pin markers in the generated layout. Default is False.
"""
def __init__(self,
ring: Any,
bus: Any,
w_bus:'float|list',
w_ring:'float|list',
sz_ring:'float|list',
sz_bus:'float|list',
name:str=None,
gap_crows:'float|list'=[0.4],
gap_cp:'float|list'=[0.45,0.45],
w_heater:'float|list'=0,
xs_heater:'str'='heater',
connected:'bool'=True,
w_metal:'float'=8,
xs_metal:'str'='metal',
via_h2m: Any = None,
isl: Any = None,
ht_shift: int=0,
A_ht: int = 45,
ISL_LEFT:'bool'=True,ISL_RIGHT:'bool'=True,
show_pins:'bool'=False) -> None:
""" """
self.ht_shift = ht_shift ## temporary variable
self.A_ht = A_ht
""" """
self.sz_ring = sz_ring
self.w_ring = w_ring
self.w_bus = w_bus
self.sz_bus = sz_bus
self.via_h2m = via_h2m
self.isl = isl
## refreshed 2022.12.28
self.gap_crows = __array_convert__(gap_crows,'gap_crows','mxpic::passive::STD_CROW_V')
self.gap_cp = __array_convert__(gap_cp,'gap_cp','mxpic::passive::STD_CROW_V')
self.name = name
if (name is None):
self.instantiate = False
else:
self.instantiate = True
self.connected = connected
if (isinstance(ring,list)):
self.ring_uniform = False
self.ring_cell = ring
self.connected = False
if (len(ring)!=len(self.gap_crows)+1):
raise Exception("ERROR: In <mxpic::passive::crows::STD_CROW_V>, ring list does not match gap list")
else :
self.ring_uniform = True
self.ring_cell = [ring]*(len(self.gap_crows)+1)
if (isinstance(bus,list)):
self.bus_uniform = False
self.bus_cell = bus
else :
self.bus_uniform = True
self.bus_cell = [bus]*(len(self.gap_cp))
### standard input rules [[sz0,sz1],[sz0,sz1],....[sz0,sz1]]
if (isinstance(self.sz_ring,int) or isinstance(self.sz_ring,float)):
self.sz_ring=[[self.sz_ring,self.sz_ring]]*len(self.ring_cell)
elif (isinstance(self.sz_ring,list)):
_sz_ = np.shape(self.sz_ring)
if (len(_sz_)==1):
self.sz_ring=[[self.sz_ring[0],self.sz_ring[1]]]*len(self.ring_cell) ## y axis
elif (_sz_[0]!=len(self.ring_cell)):
raise Exception("ERROR: In <mxpic::passive::crows::STD_CROW_V>, ring list does not match sz_ring list")
if (isinstance(self.w_ring,int) or isinstance(self.w_ring,float)):
self.w_ring=[[self.w_ring,self.w_ring]]*len(self.ring_cell) ## y axis
elif (isinstance(self.w_ring,list)):
_sz_ = np.shape(self.w_ring)
if (len(_sz_)==1):
self.w_ring=[[self.w_ring[0],self.w_ring[1]]]*len(self.ring_cell) ## y axis
elif (_sz_[0]!=len(self.ring_cell)):
raise Exception("ERROR: In <mxpic::passive::crows::STD_CROW_V>, ring list does not match w_ring list")
# print(type(w_heater))
if (isinstance(w_heater,int) or isinstance(w_heater,float)):
self.w_heater = [w_heater]*len(self.ring_cell)
else:
self.w_heater = w_heater
if (isinstance(self.w_bus,list) or isinstance(self.w_bus,np.ndarray)):
self.w_bus=self.w_bus[1] ## y axis
if (isinstance(self.sz_bus,int) or isinstance(self.sz_bus,float)):
self.sz_bus=[[self.sz_bus,self.sz_bus]] ## y axis
elif (isinstance(self.sz_bus,list)):
if (len(np.shape(self.sz_bus))==1): ## only one dimension
self.sz_bus=[self.sz_bus] ## y axis
self.cell_pic = self.generate_pic_gds()
### ================== ###
self.w_metal = w_metal
self.ISL_LEFT = ISL_LEFT
self.ISL_RIGHT = ISL_RIGHT
try :
nd.get_xsection(xs_heater)
nd.get_xsection(xs_metal)
self.xs_heater=xs_heater
self.xs_metal=xs_metal
try :
if (w_heater>0):
self.cell_eic = self.generate_eic_gds()
else :
self.cell_eic = None
except :
raise Exception("ERROR: In <mxpic.passive:STD_CROW_V>, func [generate_eic_gds] errors")
except :
self.xs_heater=None
self.xs_metal=None
self.cell_eic = None
### ======================== ###
### Building Final GDS ###
if (self.cell_eic!=None and self.cell_pic!=None):
with nd.Cell(instantiate=self.instantiate,name=self.name) as C:
try :
C_eic = self.cell_eic.put(0,0,0)
C_pic = self.cell_pic.put(0,0,0)
## transporting pins
for str,Pin in C_eic.ic_pins():
nd.Pin(name=str,pin=Pin).put()
for str,Pin in C_pic.ic_pins():
nd.Pin(name=str,pin=Pin).put()
if (show_pins):
nd.put_stub(pinsize=2)
except Exception as ex:
print("ERROR :: ",ex)
self.cell = C
elif (self.cell_eic==None and self.cell_pic!=None):
self.cell = self.cell_pic
def generate_pic_gds(self):
if (self.name is not None):
instantiate = True
name_pic = self.name + "_pic"
else:
instantiate = False
name_pic = None
with nd.Cell(instantiate=instantiate,name=name_pic) as C:
try :
instr = __cell_arg__(arg=self.ring_cell[0],arg_name="ring_cell[0]",func_name="STD_CROW_V::generate_pic_gds").put(0,0,0)
# instr.raise_pins(['r1','r2','r3','r4'],['ra1','ra2','ra3','ra4'])
# print(self.sz_ring,self.w_ring,self.gap_cp[0])
BUS_d = self.bus_cell[0].put(0,-self.sz_ring[0][1]/2-self.w_ring[0][1]/2-self.w_bus/2-self.gap_cp[0])
nd.Pin(name='a1',pin=BUS_d.pin['a1']).put()
nd.Pin(name='b1',pin=BUS_d.pin['b1']).put()
dy = 0
for _idx_ in range(0,len(self.gap_crows)):
# print(self.sz_ring)
dy = dy + self.sz_ring[_idx_][1]/2 + self.sz_ring[_idx_+1][1]/2 + self.w_ring[_idx_][1]/2+self.w_ring[_idx_+1][1]/2 + self.gap_crows[_idx_]
# instr = self.ring_cell[_idx_+1].put(0,dy,0)
instr = __cell_arg__(arg=self.ring_cell[_idx_+1],arg_name="ring_cell[_idx_+1]",func_name="STD_CROW_V::generate_pic_gds").put(0,dy,0)
if (_idx_==0):
instr.raise_pins(['r1','r2','r3','r4'],['rb1','rb2','rb3','rb4'])
if (len(self.gap_cp)==2):
BUS_u = self.bus_cell[1].put(0,dy+self.sz_ring[-1][1]/2+self.w_ring[-1][1]/2+self.w_bus/2+self.gap_cp[1],flip=1)
nd.Pin(name='a2',pin=BUS_u.pin['a1']).put()
nd.Pin(name='b2',pin=BUS_u.pin['b1']).put()
except Exception as ex:
print("ERROR :: ",ex)
return C
def generate_eic_gds(self):
with nd.Cell(instantiate=False) as C:
ht_box = [self.sz_ring[0][0],self.sz_ring[0][1]]
""" BUG : Revised 2023.04.01 """
if (self.via_h2m is None):
# self.via_h2m = Vias(xs=None,area=self.w_metal,sz=0,spacing=0,xs_l1=self.xs_heater,xs_l2=self.xs_metal) ## only putting metal blocks
VIA = Vias(xs=None,area=self.w_metal,sz=0,spacing=0,xs_l1=self.xs_heater,xs_l2=self.xs_metal) ## only putting metal blocks
else:
if (hasattr(self.via_h2m,"cell")):
# self.via_h2m = self.via_h2m
VIA = self.via_h2m
else :
# self.via_h2m = Vias(xs=self.via_h2m.xs,area=self.w_metal,sz=self.via_h2m.sz,spacing=self.via_h2m.spacing,xs_l1=self.xs_heater,xs_l2=self.xs_metal) ## placing vias
VIA = Vias(xs=self.via_h2m.xs,area=self.w_metal,sz=self.via_h2m.sz,spacing=self.via_h2m.spacing,xs_l1=self.xs_heater,xs_l2=self.xs_metal) ## placing vias
# VIA = self.via_h2m
HT,r_ht,Large_crow = self._generate_HT_box_cell_(ht_box=ht_box,w_heater=self.w_heater[0])
cell_pre = HT.put(0,0,0)
dy = 0
eic_mt = IC.Interconnect(radius=10,width=self.w_metal,xs=self.xs_metal)
eic_ht = IC.Interconnect(radius=10,width=self.w_heater[0],xs=self.xs_heater)
""" Generating heaters """
if (self.connected==True and Large_crow==False):
if (self.via_h2m is None):
temp_L = eic_ht.strt(length=self.w_metal+self.w_heater[0],pin=cell_pre.pin['ed1'],arrow=False).put()
eic_ht.strt(length=self.w_metal/2+self.ht_shift/2,width=self.w_metal).put(temp_L.pin['b0'].x,temp_L.pin['b0'].y+self.w_metal/2,180)
temp_L = VIA.cell.put(temp_L.pin['b0'].x-self.w_metal/2-self.w_heater[0]/2,temp_L.pin['b0'].y+self.w_metal/2,-90)
nd.Pin(name='ep1',pin=temp_L.pin['b0']).put()
temp_R = eic_ht.strt(length=self.w_metal+self.w_heater[0],pin=cell_pre.pin['ed2'],arrow=False).put()
eic_ht.strt(length=self.w_metal/2+self.ht_shift/2,width=self.w_metal).put(temp_R.pin['b0'].x,temp_R.pin['b0'].y+self.w_metal/2,0)
temp_R = VIA.cell.put(temp_R.pin['b0'].x+self.w_metal/2+self.w_heater[0]/2,temp_R.pin['b0'].y+self.w_metal/2,-90)
nd.Pin(name='en1',pin=temp_R.pin['b0']).put()
else:
temp_L = VIA.cell.put(cell_pre.pin['ed1'],flip=1)
nd.Pin(name='ep1',pin=temp_L.pin['b0']).put()
temp_R = VIA.cell.put(cell_pre.pin['ed2'])
nd.Pin(name='en1',pin=temp_R.pin['b0']).put()
else :
nd.Pin(name='ep1',pin=cell_pre.pin['ed1']).put()
nd.Pin(name='en1',pin=cell_pre.pin['ed2'].move(0,0,180)).put()
for _idx_ in range(0,len(self.gap_crows)):
eic_mt = IC.Interconnect(radius=10,width=self.w_metal,xs=self.xs_metal)
eic_ht = IC.Interconnect(radius=10,width=self.w_heater[_idx_],xs=self.xs_heater)
dy = dy + self.sz_ring[_idx_][1]/2 + self.sz_ring[_idx_+1][1]/2 + self.w_ring[_idx_][1]/2+self.w_ring[_idx_+1][1]/2 + self.gap_crows[_idx_]
ht_box = [self.sz_ring[_idx_+1][0],self.sz_ring[_idx_+1][1]]
HT,r_ht,Large_crow = self._generate_HT_box_cell_(ht_box=ht_box,w_heater=self.w_heater[_idx_])
cell_cur = HT.put(0,dy,0)
if (self.connected==True):
if (Large_crow==True):
eic_mt.strt_p2p(pin1=cell_pre.pin['eu1'],pin2=cell_cur.pin['ed1'],arrow=False).put()
eic_mt.strt_p2p(pin1=cell_pre.pin['eu2'],pin2=cell_cur.pin['ed2'],arrow=False).put()
else :
eic_ht.strt_p2p(pin1=cell_pre.pin['eu1'],pin2=cell_cur.pin['ed1'],arrow=False).put()
eic_ht.strt_p2p(pin1=cell_pre.pin['eu2'],pin2=cell_cur.pin['ed2'],arrow=False).put()
else :
# print(_idx_)
nd.Pin(name='ep'+str(_idx_+2),pin=cell_cur.pin['ed1']).put()
nd.Pin(name='en'+str(_idx_+2),pin=cell_cur.pin['ed2'].move(0,0,180)).put()
cell_pre = cell_cur
if (self.connected==True and Large_crow==False): ## revised in 2022.09.23, it cannot work in single ring
VIA = Vias(xs=VIA.xs,area=self.w_metal,sz=VIA.sz,spacing=VIA.spacing,xs_l1=self.xs_heater,xs_l2=self.xs_metal,
sp_via_xs=VIA.sp_via_xs)
temp_L = eic_ht.strt(length=self.w_metal+self.w_heater[-1],pin=cell_pre.pin['eu1'],arrow=False).put()
temp_L = VIA.cell.put(temp_L.pin['b0'].x-self.w_metal/2,temp_L.pin['b0'].y-self.w_metal/2,90)
temp_R = eic_ht.strt(length=self.w_metal+self.w_heater[-1],pin=cell_pre.pin['eu2'],arrow=False).put()
temp_R = VIA.cell.put(temp_R.pin['b0'].x+self.w_metal/2,temp_R.pin['b0'].y-self.w_metal/2,-90)
eic_mt.strt_p2p(pin1=temp_L.pin['b0'],pin2=temp_R.pin['b0'],arrow=False).put()
elif (self.connected==True):
eic_mt.strt_p2p(pin1=cell_pre.pin['eu1'],pin2=cell_pre.pin['eu2'],arrow=False).put()
if (self.isl is not None):
# print(dy,self.sz_ring,self.sz_bus)
L_isl = dy+self.sz_ring[0][1]/2+self.sz_ring[-1][1]/2 - self.sz_bus[0][1] - self.sz_bus[-1][1] - self.isl.sp_isl_wg*2
if (L_isl>0):
_x_ = []
for _sz_ in self.sz_ring:
_x_.append(_sz_[0])
x_isl = max(_x_)/2 + max(self.w_heater) + self.isl.sp_isl_metal
if (self.ISL_RIGHT):
ISL(xs=self.isl.xs,width=self.isl.width,length=L_isl,Lmax=self.isl.Lmax,spacing=self.isl.spacing).cell.put(x_isl,dy/2-L_isl/2,90)
if (self.ISL_LEFT):
ISL(xs=self.isl.xs,width=self.isl.width,length=L_isl,Lmax=self.isl.Lmax,spacing=self.isl.spacing).cell.put(-x_isl,dy/2-L_isl/2,90)
return C
def _generate_HT_box_cell_(self,ht_box,w_heater):
r_ht = min(ht_box)/2
l_ht = ht_box[1]-r_ht*2
if (hasattr(self,'A_ht')):
A_ht = self.A_ht
else :
A_ht = 45
Arc_ht = A_ht/180*np.pi
Large_crow = r_ht*np.sin(Arc_ht)>=self.w_metal
## generate heater unit cell
### if heater side-side distance is larger than w_metal, vias will be added
with nd.Cell(instantiate=False) as HT:
x_ht = ht_box[0]/2-r_ht+self.ht_shift/2
y_ht = ht_box[1]/2-r_ht
circle(radius=r_ht,width=w_heater,theta_start=0 ,theta_stop=A_ht,res=0.05,
xs=self.xs_heater).cell.put(x_ht,y_ht,0)
circle(radius=r_ht,width=w_heater,theta_start=180-A_ht,theta_stop=180,res=0.05,
xs=self.xs_heater).cell.put(-x_ht,y_ht,0)
nd.strt(length=l_ht,width=w_heater,xs=self.xs_heater).put(-(x_ht+r_ht),-l_ht/2,90)
nd.strt(length=l_ht,width=w_heater,xs=self.xs_heater).put( (x_ht+r_ht),-l_ht/2,90)
""" Revised in 2023.2.2, """
circle(radius=r_ht,width=w_heater,theta_start=180,theta_stop=180+A_ht,res=0.05,
xs=self.xs_heater).cell.put(-x_ht,-y_ht,0) ## revised : 2023.2.2, <x_ht> -> <x_ht>
circle(radius=r_ht,width=w_heater,theta_start=360-A_ht,theta_stop=360,res=0.05,
xs=self.xs_heater).cell.put(x_ht,-y_ht,0)
## used to see whether crow is large
""" Generate VIAS, two situations: 1. Heaters not connected, 2.Side-Side distance larger than w_metal """
if (self.connected==False or Large_crow==True):
VIA_MT = Vias(xs=self.via_h2m.xs,area=self.w_metal,sz=self.via_h2m.sz,spacing=self.via_h2m.spacing,xs_l1=self.xs_heater,xs_l2=self.xs_metal)
_x_via_ = x_ht-r_ht*(1-np.cos(Arc_ht))+r_ht
temp = VIA_MT.cell.put( _x_via_, y_ht+r_ht*np.sin(Arc_ht),0)
nd.Pin(name='eu1',pin=temp.pin['a0'].rot(180)).put()
if (self.connected==False):
nd.strt(length=r_ht*np.cos(Arc_ht)*2,width=self.w_metal,xs=self.xs_metal).put(temp.pin['a0'].x,temp.pin['a0'].y,180)
temp = VIA_MT.cell.put( _x_via_,-y_ht-r_ht*np.sin(Arc_ht),0)
nd.Pin(name='ed1',pin=temp.pin['a0'].rot(180)).put()
temp = VIA_MT.cell.put( -_x_via_, y_ht+r_ht*np.sin(Arc_ht),0)
nd.Pin(name='eu2',pin=temp.pin['a0'].rot(180)).put()
temp = VIA_MT.cell.put( -_x_via_,-y_ht-r_ht*np.sin(Arc_ht),0)
nd.Pin(name='ed2',pin=temp.pin['a0'].rot(180)).put()
else:
L_cnt = w_heater
x_ht_cnt = (r_ht-w_heater/2)*np.cos(Arc_ht)+w_heater/2+x_ht
y_ht_cnt = y_ht+(r_ht-w_heater/2)*np.sin(Arc_ht)
temp = nd.strt(length=L_cnt,width=w_heater,xs=self.xs_heater).put(-x_ht_cnt, y_ht_cnt,90)
nd.Pin(name='eu1',pin=temp.pin['b0']).put()
temp = nd.strt(length=L_cnt,width=w_heater,xs=self.xs_heater).put( x_ht_cnt, y_ht_cnt,90)
nd.Pin(name='eu2',pin=temp.pin['b0']).put()
temp = nd.strt(length=L_cnt,width=w_heater,xs=self.xs_heater).put(-x_ht_cnt,-y_ht_cnt,-90)
nd.Pin(name='ed1',pin=temp.pin['b0']).put()
temp = nd.strt(length=L_cnt,width=w_heater,xs=self.xs_heater).put( x_ht_cnt,-y_ht_cnt,-90)
nd.Pin(name='ed2',pin=temp.pin['b0']).put()
return HT,r_ht,Large_crow
class CROW_Eul_Ring(STD_CROW_V) :
"""
CROW Eul Ring primitive component.
This component builds the CROW Eul Ring layout cell.
Parameters
----------
name : str
Unique identifier for the device cell.
R0 : int, optional
Radius parameter in microns. Default is 10.
R1 : int, optional
Radius parameter in microns. Default is 3.
w0 : float, optional
Width parameter in microns. Default is 0.38.
w1 : float, optional
Width parameter in microns. Default is 0.65.
w_bus : float, optional
Width parameter in microns. Default is 0.35.
R_att : int, optional
Radius parameter in microns. Default is 15.
R_att_min : int, optional
Radius parameter in microns. Default is 3.
A_att : int, optional
Angle parameter in degrees. Default is 30.
w_wg : float, optional
Width parameter in microns. Default is 0.45.
dLx : float, optional
Value for the dLx parameter. Default is 0.
dLy : float, optional
Value for the dLy parameter. Default is 0.
xs_wg : str, optional
Layer or cross-section name used by the device. Default is 'strip'.
gap_crows : list, optional
Spacing or gap parameter in microns. Default is [0.4].
gap_cp : float, optional
Spacing or gap parameter in microns. Default is 0.45.
w_heater : float, optional
Width parameter in microns. Default is 0.
xs_heater : str, optional
Layer or cross-section name used by the device. Default is 'heater'.
connected : bool, optional
Value for the connected parameter. Default is True.
w_metal : float, optional
Width parameter in microns. Default is 8.
xs_metal : str, optional
Layer or cross-section name used by the device. Default is 'metal'.
via_h2m : Any, optional
Via definition used between heater and metal layers. Default is None.
isl : Any, optional
Isolation-trench definition used by the electrical layout. Default is None.
ISL_LEFT : bool, optional
Value for the ISL_LEFT parameter. Default is True.
ISL_RIGHT : bool, optional
Value for the ISL_RIGHT parameter. Default is True.
show_pins : bool, optional
Whether to draw pin markers in the generated layout. Default is False.
sharp_patch : bool, optional
Whether to add geometry patches for sharp corners or cladding continuity. Default is True.
dL_p2p : Optional[float], optional
Value for the dL_p2p parameter. Default is None.
Ltp_bus : int, optional
Length parameter in microns. Default is 0.
ht_shift : int, optional
Value for the ht_shift parameter. Default is 0.
A_ht : int, optional
Angle parameter in degrees. Default is 45.
R_cp : Any, optional
Radius parameter in microns. Default is None.
bus_order : float, optional
Value for the bus_order parameter. Default is 1.0.
width_type : str, optional
Width parameter in microns. Default is 'crow_customize'.
A_cp : int, optional
Angle parameter in degrees. Default is 0.
"""
def __init__(self,
name: str,
R0: int = 10, R1: int=3,
w0: float = 0.38,w1: float=0.65,
w_bus: float=0.35,
R_att: int=15,
R_att_min: int = 3,
A_att: int=30,w_wg: float=0.45,
dLx: float = 0, dLy: float=0,
xs_wg: str='strip',
gap_crows: list=[0.4],
gap_cp: float=0.45,
w_heater: float=0, xs_heater: str='heater',
connected: bool=True,
w_metal: float=8, xs_metal: str='metal',
via_h2m: Any = None,
isl: Any = None,
ISL_LEFT: bool=True, ISL_RIGHT: bool=True, show_pins: bool=False,
sharp_patch: bool=True,
dL_p2p: Optional[float] = None,
Ltp_bus: int = 0,
ht_shift: int = 0,
A_ht: int=45,
R_cp: Any = None,
bus_order: float = 1.0,
width_type: str = 'crow_customize',
A_cp: int=0,) -> None:
if (R_cp==None):
if (isinstance(gap_cp,int) or isinstance(gap_cp,float)):
R_cp = R0+w0/2+gap_cp+w_bus/2
else:
R_cp = R0+w0/2+gap_cp[0]+w_bus/2
""" Revised in 2022.11.25 """
self.w0 = w0
self.w1 = w1
self.R0 = R0
self.R1 = R1
self.xs_wg = xs_wg
self.R_att = R_att
self.A_att = A_att
self.width_type = width_type
euler = Clothoid(R = [R0,R1],w=[w0,w1],Rmax=max([R0,R1])*10,A=[0,90],xs=xs_wg,width_type=width_type,dL_wg=0.05)
ring = Racetrack(bend_cell=euler,xs=xs_wg,layer=None,dLx=dLx,dLy=dLy)
sz_ring = ring.sz
w_ring = ring.w
# ring = ring.cell
ring = ring
bus = ring_bus_wg(xs=xs_wg, R_cp=R_cp, ### Revise 2022.11.25
w_bus=w_bus,bend_DC=True, w_wg=w_wg, dAc=A_cp,
euler_anti_bend=True,euler_transistion=True,
R_max_trans=R_att,dA_trans=A_att,dL_trans=0,
w_trans=w_bus,
R_max_anti=R_att,R_min_anti=R_att_min,sharp_patch=sharp_patch,
show_pins=False,
dL_p2p=dL_p2p,
wg_Ltp=Ltp_bus,
res=0.05,
clothoid_order=bus_order
)
self.bus = bus
super().__init__(ring=ring,
name= name,
bus=bus.cell,
w_bus=bus.w,
w_ring=w_ring,
sz_ring=sz_ring,
sz_bus=bus.sz,
gap_crows=gap_crows,
gap_cp=gap_cp,
w_heater=w_heater,
xs_heater=xs_heater,
connected=connected,
w_metal=w_metal,
xs_metal=xs_metal,
via_h2m=via_h2m,
isl=isl,
ISL_LEFT=ISL_LEFT,
ISL_RIGHT=ISL_RIGHT,
show_pins=show_pins,
ht_shift=ht_shift,
A_ht=A_ht)
class CROW_Eul_RCK(STD_CROW_V) :
"""
CROW Eul RCK primitive component.
This component builds the CROW Eul RCK layout cell.
Parameters
----------
R0 : int, optional
Radius parameter in microns. Default is 10.
R1 : int, optional
Radius parameter in microns. Default is 3.
R2 : int, optional
Radius parameter in microns. Default is 20.
w0 : float, optional
Width parameter in microns. Default is 0.38.
w1 : float, optional
Width parameter in microns. Default is 0.65.
w_bus : float, optional
Width parameter in microns. Default is 0.35.
R_att : int, optional
Radius parameter in microns. Default is 15.
R_att_min : int, optional
Radius parameter in microns. Default is 3.
A_att : int, optional
Angle parameter in degrees. Default is 30.
w_wg : float, optional
Width parameter in microns. Default is 0.45.
dAc : float, optional
Value for the dAc parameter. Default is 0.
dLx : float, optional
Value for the dLx parameter. Default is 0.
dLy : float, optional
Value for the dLy parameter. Default is 0.
xs_wg : str, optional
Layer or cross-section name used by the device. Default is 'strip'.
gap_crows : list, optional
Spacing or gap parameter in microns. Default is [0.4].
gap_cp : float, optional
Spacing or gap parameter in microns. Default is 0.45.
w_heater : float, optional
Width parameter in microns. Default is 0.
xs_heater : str, optional
Layer or cross-section name used by the device. Default is 'heater'.
connected : bool, optional
Value for the connected parameter. Default is True.
w_metal : float, optional
Width parameter in microns. Default is 8.
xs_metal : str, optional
Layer or cross-section name used by the device. Default is 'metal'.
via_h2m : Any, optional
Via definition used between heater and metal layers. Default is None.
isl : Any, optional
Isolation-trench definition used by the electrical layout. Default is None.
ISL_LEFT : bool, optional
Value for the ISL_LEFT parameter. Default is True.
ISL_RIGHT : bool, optional
Value for the ISL_RIGHT parameter. Default is True.
show_pins : bool, optional
Whether to draw pin markers in the generated layout. Default is False.
sharp_patch : bool, optional
Whether to add geometry patches for sharp corners or cladding continuity. Default is True.
dL_p2p : Optional[float], optional
Value for the dL_p2p parameter. Default is None.
Ltp_bus : int, optional
Length parameter in microns. Default is 0.
ht_shift : int, optional
Value for the ht_shift parameter. Default is 0.
A_ht : int, optional
Angle parameter in degrees. Default is 45.
"""
def __init__(self,
R0: int = 10, R1: int=3,R2: int=20,
w0: float = 0.38,w1: float=0.65,
w_bus: float=0.35,
R_att: int=15,
R_att_min: int = 3,
A_att: int=30,w_wg: float=0.45,dAc: float=0,
dLx: float = 0, dLy: float=0,
xs_wg: str='strip',
gap_crows: list=[0.4],
gap_cp: float=0.45,
w_heater: float=0, xs_heater: str='heater',
connected: bool=True,
w_metal: float=8, xs_metal: str='metal',
via_h2m: Any = None,
isl: Any = None,
ISL_LEFT: bool=True, ISL_RIGHT: bool=True, show_pins: bool=False,
sharp_patch: bool=True,
dL_p2p: Optional[float] = None,
Ltp_bus: int = 0,
ht_shift: int = 0,
A_ht: int=45) -> None:
if (isinstance(gap_cp,int) or isinstance(gap_cp,float)):
R_cp = R0+w0/2+gap_cp+w_bus/2
else:
R_cp = R0+w0/2+gap_cp[0]+w_bus/2
# euler = spiral_dual(R0=R0,R1=R1,R2=R2,w0=w0,w1=w1,Rmax=max([R0,R1,R2])*10,xs=xs_wg,width_type='sine')
""" Revised in 2022.11.25 """
euler = Clothoid(R = [R0,R1,R2],w=[w0,w1],Rmax=max([R0,R1,R2])*10,A=[0,45,90],xs=xs_wg,width_type='sine' )
ring = Racetrack(bend_cell=euler,xs=xs_wg,layer=None,dLx=dLx,dLy=dLy)
sz_ring = ring.sz
w_ring = ring.w
ring = ring.cell
# ring,sz_ring,w_ring = euler.racetrack(dLy=dLy,dLx=dLx)
bus = ring_bus_wg(xs=xs_wg, R_cp=R_cp, ### Revise 2022.11.25
w_bus=w_bus,bend_DC=True, w_wg=w_wg, dAc=dAc,
euler_anti_bend=True,euler_transistion=True,
R_max_trans=R_att,dA_trans=A_att,dL_trans=0,
w_trans=w_bus,
R_max_anti=R_att,R_min_anti=R_att_min,sharp_patch=sharp_patch,
show_pins=False,
dL_p2p=dL_p2p,
wg_Ltp=Ltp_bus,
)
super().__init__(ring=ring,
bus=bus.cell,
w_bus=bus.w,
w_ring=w_ring,
sz_ring=sz_ring,
sz_bus=bus.sz,
gap_crows=gap_crows,
gap_cp=gap_cp,
w_heater=w_heater,
xs_heater=xs_heater,
connected=connected,
w_metal=w_metal,
xs_metal=xs_metal,
via_h2m=via_h2m,
isl=isl,
ISL_LEFT=ISL_LEFT,
ISL_RIGHT=ISL_RIGHT,
show_pins=show_pins,
ht_shift=ht_shift,
A_ht=A_ht)
""" Circular ring """
class CROW_Circular_ring(STD_CROW_V):
"""
CROW Circular ring primitive component.
This component builds the CROW Circular ring layout cell.
Parameters
----------
r_ring : float, optional
Radius parameter in microns. Default is 10.
w_ring : float, optional
Width parameter in microns. Default is 0.45.
xs_ring : str, optional
Layer or cross-section name used by the device. Default is 'strip'.
w1_bus : float, optional
Value for the w1_bus parameter. Default is 0.45.
A1_cp : int, optional
Angle parameter in degrees. Default is 10.
w2_bus : float, optional
Value for the w2_bus parameter. Default is 0.45.
A2_cp : int, optional
Angle parameter in degrees. Default is 10.
gap1 : float, optional
Spacing or gap parameter in microns. Default is 0.45.
gap2 : float, optional
Spacing or gap parameter in microns. Default is 0.45.
w_wg : float, optional
Width parameter in microns. Default is 0.45.
Euler_trasition : bool, optional
Value for the Euler_trasition parameter. Default is True.
R1_cp : Any, optional
Radius parameter in microns. Default is None.
R2_cp : Any, optional
Radius parameter in microns. Default is None.
R1_att : float, optional
Radius parameter in microns. Default is 10.
R2_att : float, optional
Radius parameter in microns. Default is 10.
R1_att_min : float, optional
Radius parameter in microns. Default is 5.
R2_att_min : float, optional
Radius parameter in microns. Default is 5.
A1_att : int, optional
Angle parameter in degrees. Default is 45.
A2_att : int, optional
Angle parameter in degrees. Default is 45.
gap_crows : float or list, optional
Spacing or gap parameter in microns. Default is [0.4].
w_heater : float or list, optional
Width parameter in microns. Default is 0.
xs_heater : str, optional
Layer or cross-section name used by the device. Default is 'heater'.
connected : bool, optional
Value for the connected parameter. Default is True.
w_metal : float, optional
Width parameter in microns. Default is 8.
xs_metal : str, optional
Layer or cross-section name used by the device. Default is 'metal'.
via_h2m : Any, optional
Via definition used between heater and metal layers. Default is None.
isl : Any, optional
Isolation-trench definition used by the electrical layout. Default is None.
ISL_LEFT : bool, optional
Value for the ISL_LEFT parameter. Default is True.
ISL_RIGHT : bool, optional
Value for the ISL_RIGHT parameter. Default is True.
show_pins : bool, optional
Whether to draw pin markers in the generated layout. Default is False.
sharp_patch : bool, optional
Whether to add geometry patches for sharp corners or cladding continuity. Default is True.
dL_p2p : Optional[float], optional
Value for the dL_p2p parameter. Default is None.
Ltp_bus : int, optional
Length parameter in microns. Default is 0.
ht_shift : int, optional
Value for the ht_shift parameter. Default is 0.
A_ht : int, optional
Angle parameter in degrees. Default is 45.
"""
def __init__(self,
r_ring: float = 10, w_ring:float = 0.45,xs_ring: str='strip',
w1_bus: float = 0.45,A1_cp: int = 10,
w2_bus: float = 0.45,A2_cp: int = 10,
gap1: float = 0.45, gap2: float = 0.45,
w_wg: float = 0.45,
Euler_trasition: bool=True,
R1_cp: Any = None,
R2_cp: Any = None,
R1_att:float = 10,
R2_att:float = 10,
R1_att_min: float = 5,
R2_att_min: float = 5,
A1_att: int = 45,
A2_att: int = 45,
gap_crows: 'float|list' = [0.4],
w_heater: 'float|list' = 0, xs_heater: 'str' = 'heater',
connected: 'bool' = True, w_metal: 'float' = 8,
xs_metal: 'str' = 'metal',
via_h2m: Any = None,
isl: Any = None,
ISL_LEFT: 'bool' = True, ISL_RIGHT: 'bool' = True,
show_pins: 'bool' = False,
sharp_patch: bool = True,
dL_p2p: Optional[float] = None,
Ltp_bus: int = 0,
ht_shift: int=0,
A_ht: int = 45) -> None:
## defining ring list
if (isinstance(r_ring,int) or isinstance(r_ring,float)):
ring = circle(radius=r_ring,width=w_ring,
# n_points=128,
res=0.05,
xs=xs_ring)
ring_cell = ring.cell
ring_sz = ring.sz
ring_w = ring.w
r_ring = [r_ring]
w_ring = [w_ring]
elif (isinstance(r_ring,list) or isinstance(r_ring,np.ndarray)):
if (len(r_ring)!=len(w_ring)):
raise Exception("ERROR: In <mxpic::passive::STD_circle_ring_CROW>, <r_ring> does not match <w_ring>")
ring_cell = []
ring_sz = []
ring_w = []
for _idx_ in range(0,len(r_ring)):
_ring_ = circle(radius=r_ring[_idx_],width=w_ring[_idx_],res=0.05,
# n_points=128,
xs=xs_ring)
ring_cell.append(_ring_.cell)
ring_sz.append(_ring_.sz)
ring_w.append(_ring_.w)
## expand to N*2 dimension list, [[sz0,sz1],[sz0,sz1]]
# ring_sz = [ring_sz,ring_sz]
# ring_w = [ring_w,ring_w]
else :
raise Exception("ERROR: In <mxpic::passive::STD_circle_ring_CROW>, <r_ring> is not recongized, please input type <int,float,list,numpy.ndarray>")
if (w1_bus<=0):
raise Exception("ERROR: In <mxpic::passive::STD_circle_ring_CROW>, <w1_bus> should larger than 0")
if (R1_cp==None):
R1_cp = w1_bus/2 + r_ring[0] + w_ring[0]/2 + gap1
BUS_U = ring_bus_wg(xs=xs_ring, R_cp=R1_cp, ### Revise 2022.11.25
w_bus=w1_bus,bend_DC=True, w_wg=w_wg, dAc=A1_cp,
euler_anti_bend=Euler_trasition,euler_transistion=Euler_trasition,
R_max_trans=R1_att,dA_trans=A1_att,dL_trans=0,
w_trans=w1_bus,
R_max_anti=R1_att,R_min_anti=R1_att_min,sharp_patch=sharp_patch,
show_pins=False,
dL_p2p=dL_p2p,
wg_Ltp=Ltp_bus,
res=0.05,
)
bus_cell = [BUS_U.cell]
bus_w = BUS_U.w
bus_sz = BUS_U.sz
gap_cp = [gap1]
""" Add-drop CROW """
if (w2_bus>0):
if (R2_cp==None):
R2_cp = w2_bus/2 + r_ring[-1] + w_ring[-1]/2 + gap2
BUS_D = ring_bus_wg(xs=xs_ring, R_cp=R2_cp, ### Revise 2022.11.25
w_bus=w2_bus,bend_DC=True, w_wg=w_wg, dAc=A2_cp,
euler_anti_bend=Euler_trasition,euler_transistion=Euler_trasition,
R_max_trans=R2_att,dA_trans=A2_att,dL_trans=0,
w_trans=w2_bus,
R_max_anti=R2_att,R_min_anti=R2_att_min,sharp_patch=sharp_patch,
show_pins=False,
dL_p2p=dL_p2p,
wg_Ltp=Ltp_bus,
)
bus_cell = [BUS_U.cell,BUS_D.cell]
bus_w = [BUS_U.w,BUS_D.w]
bus_sz = [BUS_U.sz,BUS_D.sz]
gap_cp = [gap1,gap2]
super().__init__(ring=ring_cell,
bus=bus_cell,
w_bus=bus_w,
w_ring=ring_w,
sz_ring=ring_sz,
sz_bus=bus_sz,
gap_crows=gap_crows,
gap_cp=gap_cp,
w_heater=w_heater,
xs_heater=xs_heater,
connected=connected,
w_metal=w_metal,
xs_metal=xs_metal,
via_h2m=via_h2m,
isl=isl,
ISL_LEFT=ISL_LEFT,
ISL_RIGHT=ISL_RIGHT,
show_pins=show_pins,
ht_shift=ht_shift,
A_ht=A_ht)
""" CROW with standard identical ring """
class CROW_STD_Allpass(CROW_Circular_ring):
"""
CROW STD Allpass primitive component.
This component builds the CROW STD Allpass layout cell.
Parameters
----------
r_ring : float, optional
Radius parameter in microns. Default is 10.
w_ring : float, optional
Width parameter in microns. Default is 0.45.
xs_ring : str, optional
Layer or cross-section name used by the device. Default is 'strip'.
w_bus : float, optional
Width parameter in microns. Default is 0.45.
A_cp : int, optional
Angle parameter in degrees. Default is 10.
gap_bus : float, optional
Spacing or gap parameter in microns. Default is 0.45.
w_wg : float, optional
Width parameter in microns. Default is 0.45.
Euler_trasition : bool, optional
Value for the Euler_trasition parameter. Default is True.
R_att : float, optional
Radius parameter in microns. Default is 10.
R_att_min : float, optional
Radius parameter in microns. Default is 5.
A_att : int, optional
Angle parameter in degrees. Default is 45.
gap_crows : float or list, optional
Spacing or gap parameter in microns. Default is [0.4].
w_heater : float or list, optional
Width parameter in microns. Default is 0.
xs_heater : str, optional
Layer or cross-section name used by the device. Default is 'heater'.
connected : bool, optional
Value for the connected parameter. Default is True.
w_metal : float, optional
Width parameter in microns. Default is 8.
xs_metal : str, optional
Layer or cross-section name used by the device. Default is 'metal'.
via_h2m : Any, optional
Via definition used between heater and metal layers. Default is None.
isl : Any, optional
Isolation-trench definition used by the electrical layout. Default is None.
show_pins : bool, optional
Whether to draw pin markers in the generated layout. Default is False.
sharp_patch : bool, optional
Whether to add geometry patches for sharp corners or cladding continuity. Default is True.
dL_p2p : Optional[float], optional
Value for the dL_p2p parameter. Default is None.
Ltp_bus : int, optional
Length parameter in microns. Default is 0.
ht_shift : int, optional
Value for the ht_shift parameter. Default is 0.
A_ht : int, optional
Angle parameter in degrees. Default is 45.
"""
def __init__(self,
r_ring: float=10,
w_ring: float = 0.45,
xs_ring: str='strip',
w_bus: float=0.45,
A_cp: int=10,
gap_bus: float=0.45,
w_wg: float=0.45,
Euler_trasition: bool=True,
R_att: float = 10,
R_att_min: float = 5,
A_att: int=45,
gap_crows: 'float|list' = [0.4],
w_heater: 'float|list' = 0,
xs_heater: 'str' = 'heater',
connected: 'bool' = True,
w_metal: 'float' = 8,
xs_metal: 'str' = 'metal',
via_h2m: Any=None,
isl: Any=None,
show_pins: 'bool' = False,
sharp_patch: bool=True,
dL_p2p: Optional[float]=None,
Ltp_bus: int=0,
ht_shift: int=0,
A_ht: int=45) -> None:
super().__init__(r_ring=r_ring, w_ring=w_ring,
xs_ring=xs_ring,
w1_bus=w_bus,
A1_cp=A_cp,
w2_bus=0,
A2_cp=0,
gap1=gap_bus,
gap2=gap_bus,
w_wg=w_wg,
Euler_trasition=Euler_trasition,
R1_cp=None,
R2_cp=None,
R1_att=R_att,
R2_att=R_att,
R1_att_min=R_att_min,
R2_att_min=R_att_min,
A1_att=A_att,
A2_att=A_att,
gap_crows=gap_crows,
w_heater=w_heater,
xs_heater=xs_heater,
connected=connected,
w_metal=w_metal,
xs_metal=xs_metal,
via_h2m=via_h2m,
isl=isl,
ISL_LEFT=True,
ISL_RIGHT=True,
show_pins=show_pins,
sharp_patch=sharp_patch,
dL_p2p=dL_p2p,
Ltp_bus=Ltp_bus,
ht_shift=ht_shift,
A_ht=A_ht)
class CROW_STD_Adddrop(CROW_Circular_ring):
"""
CROW STD Adddrop primitive component.
This component builds the CROW STD Adddrop layout cell.
Parameters
----------
r_ring : float, optional
Radius parameter in microns. Default is 10.
w_ring : float, optional
Width parameter in microns. Default is 0.45.
xs_ring : str, optional
Layer or cross-section name used by the device. Default is 'strip'.
w_bus : float, optional
Width parameter in microns. Default is 0.45.
A_cp : int, optional
Angle parameter in degrees. Default is 10.
gap_bus : float, optional
Spacing or gap parameter in microns. Default is 0.45.
w_wg : float, optional
Width parameter in microns. Default is 0.45.
Euler_trasition : bool, optional
Value for the Euler_trasition parameter. Default is True.
R_att : float, optional
Radius parameter in microns. Default is 10.
R_att_min : float, optional
Radius parameter in microns. Default is 5.
A_att : int, optional
Angle parameter in degrees. Default is 45.
gap_crows : float or list, optional
Spacing or gap parameter in microns. Default is [0.4].
w_heater : float or list, optional
Width parameter in microns. Default is 0.
xs_heater : str, optional
Layer or cross-section name used by the device. Default is 'heater'.
connected : bool, optional
Value for the connected parameter. Default is True.
w_metal : float, optional
Width parameter in microns. Default is 8.
xs_metal : str, optional
Layer or cross-section name used by the device. Default is 'metal'.
via_h2m : Any, optional
Via definition used between heater and metal layers. Default is None.
isl : Any, optional
Isolation-trench definition used by the electrical layout. Default is None.
show_pins : bool, optional
Whether to draw pin markers in the generated layout. Default is False.
sharp_patch : bool, optional
Whether to add geometry patches for sharp corners or cladding continuity. Default is True.
dL_p2p : Optional[float], optional
Value for the dL_p2p parameter. Default is None.
Ltp_bus : int, optional
Length parameter in microns. Default is 0.
ht_shift : int, optional
Value for the ht_shift parameter. Default is 0.
A_ht : int, optional
Angle parameter in degrees. Default is 45.
"""
def __init__(self,
r_ring: float=10,
w_ring: float = 0.45,
xs_ring: str='strip',
w_bus: float=0.45,
A_cp: int=10,
gap_bus: float=0.45,
w_wg: float=0.45,
Euler_trasition: bool=True,
R_att: float = 10,
R_att_min: float = 5,
A_att: int=45,
gap_crows: 'float|list' = [0.4],
w_heater: 'float|list' = 0,
xs_heater: 'str' = 'heater',
connected: 'bool' = True,
w_metal: 'float' = 8,
xs_metal: 'str' = 'metal',
via_h2m: Any=None,
isl: Any=None,
show_pins: 'bool' = False,
sharp_patch: bool=True,
dL_p2p: Optional[float]=None,
Ltp_bus: int=0,
ht_shift: int=0,
A_ht: int=45) -> None:
super().__init__(r_ring=r_ring, w_ring=w_ring,
xs_ring=xs_ring,
w1_bus=w_bus,
A1_cp=A_cp,
w2_bus=w_bus,
A2_cp=A_cp,
gap1=gap_bus,
gap2=gap_bus,
w_wg=w_wg,
Euler_trasition=Euler_trasition,
R1_cp=None,
R2_cp=None,
R1_att=R_att,
R2_att=R_att,
R1_att_min=R_att_min,
R2_att_min=R_att_min,
A1_att=A_att,
A2_att=A_att,
gap_crows=gap_crows,
w_heater=w_heater,
xs_heater=xs_heater,
connected=connected,
w_metal=w_metal,
xs_metal=xs_metal,
via_h2m=via_h2m,
isl=isl,
ISL_LEFT=True,
ISL_RIGHT=True,
show_pins=show_pins,
sharp_patch=sharp_patch,
dL_p2p=dL_p2p,
Ltp_bus=Ltp_bus,
ht_shift=ht_shift,
A_ht=A_ht)
""" Adiabatic Elipse Diameter """
class CROW_AED(STD_CROW_V):
"""
CROW AED primitive component.
This component builds the CROW AED layout cell.
Parameters
----------
r_outer : float, optional
Radius parameter in microns. Default is 10.
wa : float, optional
Width parameter in microns. Default is 0.45.
wb : float, optional
Width parameter in microns. Default is 0.45.
xs_ring : str, optional
Layer or cross-section name used by the device. Default is 'strip'.
w1_bus : float, optional
Value for the w1_bus parameter. Default is 0.45.
A1_cp : int, optional
Angle parameter in degrees. Default is 10.
w2_bus : float, optional
Value for the w2_bus parameter. Default is 0.45.
A2_cp : int, optional
Angle parameter in degrees. Default is 10.
gap1 : float, optional
Spacing or gap parameter in microns. Default is 0.45.
gap2 : float, optional
Spacing or gap parameter in microns. Default is 0.45.
w_wg : float, optional
Width parameter in microns. Default is 0.45.
Euler_trasition : bool, optional
Value for the Euler_trasition parameter. Default is True.
R1_cp : float, optional
Radius parameter in microns. Default is None.
R2_cp : float, optional
Radius parameter in microns. Default is None.
R1_att : float, optional
Radius parameter in microns. Default is 15.
R2_att : float, optional
Radius parameter in microns. Default is 15.
R1_att_min : float, optional
Radius parameter in microns. Default is 5.
R2_att_min : float, optional
Radius parameter in microns. Default is 5.
L_tilt : int, optional
Length parameter in microns. Default is 0.
A1_att : int, optional
Angle parameter in degrees. Default is 45.
A2_att : int, optional
Angle parameter in degrees. Default is 45.
Ltp_bus : int, optional
Length parameter in microns. Default is 0.
dL_p2p : Optional[float], optional
Value for the dL_p2p parameter. Default is None.
gap_crows : float or list, optional
Spacing or gap parameter in microns. Default is [0.4].
gap_cp : float or list, optional
Spacing or gap parameter in microns. Default is [0.45, 0.45].
w_heater : float or list, optional
Width parameter in microns. Default is 0.
xs_heater : str, optional
Layer or cross-section name used by the device. Default is 'heater'.
connected : bool, optional
Value for the connected parameter. Default is True.
w_metal : float, optional
Width parameter in microns. Default is 8.
xs_metal : str, optional
Layer or cross-section name used by the device. Default is 'metal'.
via_h2m : Any, optional
Via definition used between heater and metal layers. Default is None.
isl : Any, optional
Isolation-trench definition used by the electrical layout. Default is None.
ISL_LEFT : bool, optional
Value for the ISL_LEFT parameter. Default is True.
ISL_RIGHT : bool, optional
Value for the ISL_RIGHT parameter. Default is True.
show_pins : bool, optional
Whether to draw pin markers in the generated layout. Default is False.
sharp_patch : bool, optional
Whether to add geometry patches for sharp corners or cladding continuity. Default is True.
ht_shift : int, optional
Value for the ht_shift parameter. Default is 0.
A_ht : int, optional
Angle parameter in degrees. Default is 45.
"""
def __init__(self,
r_outer: float = 10,
wa: float = 0.45,
wb: float = 0.45,
xs_ring: str='strip',
w1_bus: float = 0.45,A1_cp: int = 10,
w2_bus: float = 0.45,A2_cp: int = 10,
gap1: float = 0.45, gap2: float = 0.45,
w_wg: float = 0.45,
Euler_trasition: bool=True,
R1_cp:float = None,
R2_cp:float = None,
R1_att:float = 15,
R2_att:float = 15,
R1_att_min:float = 5,
R2_att_min:float = 5,
L_tilt: int = 0,
A1_att: int = 45,
A2_att: int = 45,
Ltp_bus: int = 0,
dL_p2p: Optional[float]=None,
gap_crows: 'float|list' = [0.4],
gap_cp: 'float|list' = [0.45, 0.45],
w_heater: 'float|list' = 0, xs_heater: 'str' = 'heater',
connected: 'bool' = True, w_metal: 'float' = 8,
xs_metal: 'str' = 'metal',
via_h2m: Any = None,
isl: Any = None,
ISL_LEFT: 'bool' = True, ISL_RIGHT: 'bool' = True,
show_pins: 'bool' = False,
sharp_patch: bool=True,
ht_shift: int = 0,
A_ht: int=45) -> None:
## defining ring list
if (isinstance(r_outer,int) or isinstance(r_outer,float)):
ring = Elipse_dual(ORx=r_outer,ORy=r_outer,IRx=r_outer-wa,IRy=r_outer-wb,
# n_points=128,
xs=xs_ring)
ring_cell = ring.cell
ring_sz = ring.sz
ring_w = ring.wb
r_outer = [r_outer]
wa = [wa]
wb = [wb]
elif (isinstance(r_outer,list) or isinstance(r_outer,np.ndarray)):
if (len(r_outer)!=len(wa)):
raise Exception("ERROR: In <mxpic::passive::STD_circle_ring_CROW>, <r_outer> does not match <w_ring>")
ring_cell = []
ring_sz = []
ring_w = []
for _idx_ in range(0,len(r_outer)):
_ring_ = Elipse_dual(ORx=r_outer[_idx_],ORy=r_outer[_idx_],IRx=r_outer[_idx_]-wa[_idx_],IRy=r_outer[_idx_]-wb[_idx_],
# n_points=128,
xs=xs_ring)
ring_cell.append(_ring_.cell)
ring_sz.append(_ring_.sz)
ring_w.append(_ring_.wb)
## expand to N*2 dimension list, [[sz0,sz1],[sz0,sz1]]
# ring_sz = [ring_sz,ring_sz]
# ring_w = [ring_w,ring_w]
else :
raise Exception("ERROR: In <mxpic::passive::STD_circle_ring_CROW>, <r_ring> is not recongized, please input type <int,float,list,numpy.ndarray>")
if (w1_bus<=0):
raise Exception("ERROR: In <mxpic::passive::STD_circle_ring_CROW>, <w1_bus> should larger than 0")
R1_cp = w1_bus/2 + r_outer[0] + wb[0]/2 + gap1
### generating coupling BUS waveguide
BUS_U = ring_bus_wg(xs=xs_ring, R_cp=R1_cp,
w_bus=w1_bus,bend_DC=True, w_wg=w_wg, dAc=A1_cp,
euler_anti_bend=Euler_trasition,euler_transistion=Euler_trasition,
R_max_trans=R1_att,dA_trans=A1_att,dL_trans=L_tilt,
w_trans=w1_bus,
R_max_anti=R1_att,R_min_anti=R1_att_min,sharp_patch=sharp_patch,show_pins=show_pins,
dL_p2p=dL_p2p,
wg_Ltp=Ltp_bus,
)
bus_cell = [BUS_U.cell]
bus_w = BUS_U.w
bus_sz = BUS_U.sz
if (w2_bus>0):
R2_cp = w2_bus/2 + r_outer[-1] + wb[-1]/2 + gap2
BUS_D = ring_bus_wg(xs=xs_ring, R_cp=R2_cp,
w_bus=w2_bus,bend_DC=True, w_wg=w_wg, dAc=A2_cp,
euler_anti_bend=Euler_trasition,euler_transistion=Euler_trasition,
R_max_trans=R2_att,dA_trans=A2_att,dL_trans=L_tilt,
w_trans=w2_bus,
R_max_anti=R2_att,R_min_anti=R2_att_min,sharp_patch=sharp_patch,show_pins=show_pins,
dL_p2p=dL_p2p,
wg_Ltp=Ltp_bus,)
bus_cell = [BUS_U.cell,BUS_D.cell]
bus_w = [BUS_U.w,BUS_D.w]
bus_sz = [BUS_U.sz,BUS_D.sz]
super().__init__(ring=ring_cell,
bus=bus_cell,
w_bus=bus_w,
w_ring=ring_w,
sz_ring=ring_sz,
sz_bus=bus_sz,
gap_crows=gap_crows,
gap_cp=gap_cp,
w_heater=w_heater,
xs_heater=xs_heater,
connected=connected,
w_metal=w_metal,
xs_metal=xs_metal,
via_h2m=via_h2m,
isl=isl,
ISL_LEFT=ISL_LEFT,
ISL_RIGHT=ISL_RIGHT,
show_pins=show_pins,
ht_shift=ht_shift,
A_ht=A_ht)