from__future__importannotationsimportnumpyasnpimportgdsfactoryasgffromgdsfactoryimportComponentfromgdsfactory.typingsimportComponentSpec,CrossSectionSpec,LayerSpecdef_compute_parameters(xs_bend,wrap_angle_deg,radius):r_bend=xs_bend.radiustheta=wrap_angle_deg/2.0size_x,dy=(r_bend*np.sin(theta*np.pi/180),r_bend-r_bend*np.cos(theta*np.pi/180),)bus_length=max(4*size_x,2*radius)return(r_bend,size_x,dy,bus_length)def_generate_bends(c,r_bend,wrap_angle_deg,cross_section):ifwrap_angle_deg!=0:input_arc=gf.path.arc(radius=r_bend,angle=-wrap_angle_deg/2.0)bend_middle_arc=gf.path.arc(radius=r_bend,angle=-wrap_angle_deg)bend_input_output=input_arc.extrude(cross_section=cross_section)bend_input=c<<bend_input_outputbend_middle=c<<bend_middle_arc.extrude(cross_section=cross_section)bend_middle.rotate(180+wrap_angle_deg/2.0,center=c.center)bend_input.connect("o2",bend_middle.ports["o2"])bend_output=c<<bend_input_outputbend_output.mirror()bend_output.connect("o2",bend_middle.ports["o1"])return(c,bend_input,bend_middle,bend_output)else:return(c,None,None,None)def_generate_straights(c,bus_length,size_x,bend_input,bend_output,cross_section):straight_left=c<<gf.components.straight(length=(bus_length-4*size_x)/2.0,cross_section=cross_section)straight_right=c<<gf.components.straight(length=(bus_length-4*size_x)/2.0,cross_section=cross_section)ifNonenotin(bend_input,bend_output):straight_left.connect("o2",bend_input.ports["o1"])straight_right.connect("o1",bend_output.ports["o1"])else:straight_left.connect("o2",straight_right.ports["o1"])return(c,straight_left,straight_right)def_generate_circles(c,radius:float,xs,bend_middle,straight_left,r_bend,dy:float):"""Returns Component, circle and circle_cladding. Args: c: component. radius: in um. xs: cross_section: bend_middle: bend spec. straight_left: spec. r_bend: spec. dy: in um. """circle=c<<gf.components.circle(radius=radius,layer=xs.layer)circle_cladding=Noneifbend_middleisnotNone:circle.move(origin=circle.center,destination=((bend_middle.ports["o1"].x+bend_middle.ports["o2"].x)/2.0,straight_left.ports["o2"].y-2*dy+r_bend,),)else:circle.move(origin=circle.center,destination=(straight_left.ports["o2"].center+(0,r_bend)),)ifcircle_cladding:circle_cladding.move(origin=circle_cladding.center,destination=circle.center)return(c,circle,circle_cladding)def_absorb(c,*refs):forrefinlist(refs):ifrefisnotNone:c.absorb(ref)returnc
[docs]@gf.celldefdisk(radius:float=10.0,gap:float=0.2,wrap_angle_deg:float=180.0,parity:int=1,cross_section:CrossSectionSpec="xs_sc",)->Component:"""Disk Resonator. Args: radius: disk resonator radius. gap: Distance between the bus straight and resonator. wrap_angle_deg: Angle in degrees between 0 and 180. determines how much the bus straight wraps along the resonator. 0 corresponds to a straight bus straight. 180 corresponds to a bus straight wrapped around half of the resonator. parity (1 or -1): 1, resonator left from bus straight, -1 resonator to the right. cross_section: cross_section spec. """ifparitynotin(1,-1):raiseValueError("parity must be 1 or -1")ifwrap_angle_deg<0.0orwrap_angle_deg>180.0:raiseValueError("wrap_angle_deg must be between 0.0 and 180.0")c=gf.Component()xs=gf.get_cross_section(cross_section=cross_section)radius_disk=radiusradius=radius+xs.width/2.0+gapxs_bend=xs.copy(radius=radius)r_bend,size_x,dy,bus_length=_compute_parameters(xs_bend,wrap_angle_deg,radius)c,bend_input,bend_middle,bend_output=_generate_bends(c,r_bend,wrap_angle_deg,xs_bend)c,straight_left,straight_right=_generate_straights(c,bus_length,size_x,bend_input,bend_output,xs_bend)c,circle,circle_cladding=_generate_circles(c,radius_disk,xs,bend_middle,straight_left,r_bend,dy)c=_absorb(c,circle,circle_cladding,straight_left,straight_right,bend_input,bend_middle,bend_output,)c.add_port("o1",port=straight_left.ports["o1"],layer="PORT")c.add_port("o2",port=straight_right.ports["o2"])xs.add_bbox(c)ifparity==-1:c=c.rotate(180)returnc
[docs]@gf.celldefdisk_heater(radius:float=10.0,gap:float=0.2,wrap_angle_deg:float=180.0,parity:int=1,cross_section:CrossSectionSpec="xs_sc",heater_layer:LayerSpec="HEATER",via_stack:ComponentSpec="via_stack_heater_mtop",heater_width:float=5.0,heater_extent:float=2.0,via_width:float=10.0,port_orientation:float|None=90,)->Component:"""Disk Resonator with top metal heater. Args: radius: disk resonator radius. gap: Distance between the bus straight and resonator. wrap_angle_deg: Angle in degrees between 0 and 180. determines how much the bus straight wraps along the resonator. 0 corresponds to a straight bus straight. 180 corresponds to a bus straight wrapped around half of the resonator. parity (1 or -1): 1, resonator left from bus straight, -1 resonator to the right. cross_section: cross_section spec. heater_layer: layer of the heater. heater_width: width of the heater. heater_extent: length of heater beyond disk. via_width: size of the square via at the end of the heater. port_orientation: in degrees. """c=gf.Component()xs=gf.get_cross_section(cross_section=cross_section)disk_instance=c<<disk(radius=radius,gap=gap,wrap_angle_deg=wrap_angle_deg,parity=parity,cross_section=cross_section,)dx=disk_instance.xmax-disk_instance.xmindy=disk_instance.ymax-disk_instance.yminheater=c<<gf.get_component(gf.components.rectangle,size=(dx+2*heater_extent,heater_width),layer=heater_layer,)heater.x=disk_instance.xheater.y=dy/2+disk_instance.ymin+(xs.width+gap)/2via=gf.get_component(via_stack,size=(via_width,via_width))c1=c<<viac2=c<<viac1.xmax=heater.xminc1.y=heater.yc2.xmin=heater.xmaxc2.y=heater.yc.add_ports(disk_instance.get_ports_list())c.add_ports(c1.get_ports_list(orientation=port_orientation),prefix="e1")c.add_ports(c2.get_ports_list(orientation=port_orientation),prefix="e2")c.auto_rename_ports()returnc
if__name__=="__main__":# c = disk_heater(wrap_angle_deg=75)c=disk(wrap_angle_deg=000000000)c.show(show_ports=True)