[docs]@celldefoptimal_step(start_width:float=10,end_width:float=22,num_pts:int=50,width_tol:float=1e-3,anticrowding_factor:float=1.2,symmetric:bool=False,layer:LayerSpec=(1,0),)->Component:"""Returns an optimally-rounded step geometry. Args: start_width: Width of the connector on the left end of the step. end_width: Width of the connector on the right end of the step. num_pts: number of points comprising the entire step geometry. width_tol: Point at which to terminate the calculation of the optimal step anticrowding_factor: Factor to reduce current crowding by elongating the structure and reducing the curvature symmetric: If True, adds a mirrored copy of the step across the x-axis to the geometry and adjusts the width of the ports. layer: layer spec to put polygon geometry on. based on phidl.geometry Notes ----- Optimal structure from https://doi.org/10.1103/PhysRevB.84.174510 Clem, J., & Berggren, K. (2011). Geometry-dependent critical currents in superconducting nanocircuits. Physical Review B, 84(17), 1–27. """defstep_points(eta,W,a):"""Returns step points. Returns points from a unit semicircle in the w (= u + iv) plane to the optimal curve in the zeta (= x + iy) plane which transitions a wire from a width of 'W' to a width of 'a' eta takes value 0 to pi """W=np.array(W,dtype=complex)a=np.array(a,dtype=complex)gamma=(a**2+W**2)/(a**2-W**2)w=np.exp(1j*eta)zeta=(4*1j/np.pi*(W*np.arctan(np.sqrt((w-gamma)/(gamma+1)))+a*np.arctan(np.sqrt((gamma-1)/(w-gamma)))))x=np.real(zeta)y=np.imag(zeta)returnx,ydefinvert_step_point(x_desired=-10,y_desired=None,W=1,a=2):# Finds the eta associated with the value x_desired along the# optimal curvedeffh(eta):guessed_x,guessed_y=step_points(eta,W=W,a=a)ify_desiredisNone:return(guessed_x-x_desired)**2# The errorelse:return(guessed_y-y_desired)**2try:fromscipy.optimizeimportfminboundexceptExceptionase:raiseImportError("To run the optimal-curve geometry ""functions you need scipy, please install ""it with `pip install scipy`")fromefound_eta=fminbound(fh,x1=0,x2=np.pi,args=())returnstep_points(found_eta,W=W,a=a)ifstart_width>end_width:reverse=Truestart_width,end_width=end_width,start_widthelse:reverse=FalseD=Component()ifstart_width==end_width:# Just return a squareifsymmetric:ypts=[-start_width/2,start_width/2,start_width/2,-start_width/2,]xpts=[0,0,start_width,start_width]ifnotsymmetric:ypts=[0,start_width,start_width,0]xpts=[0,0,start_width,start_width]D.info["num_squares"]=1else:xmin,ymin=invert_step_point(y_desired=start_width*(1+width_tol),W=start_width,a=end_width)xmax,ymax=invert_step_point(y_desired=end_width*(1-width_tol),W=start_width,a=end_width)xpts=np.linspace(xmin,xmax,num_pts).tolist()ypts=[]forxinxpts:x,y=invert_step_point(x_desired=x,W=start_width,a=end_width)ypts.append(y)ypts[-1]=end_widthypts[0]=start_widthy_num_sq=np.array(ypts)x_num_sq=np.array(xpts)ifnotsymmetric:xpts.append(xpts[-1])ypts.append(0)xpts.append(xpts[0])ypts.append(0)else:xpts+=list(xpts[::-1])ypts+=[-yforyinypts[::-1]]xpts=[x/2forxinxpts]ypts=[y/2foryinypts]# anticrowding_factor stretches the wire out; a stretched wire is a# gentler transition, so there's less chance of current crowding if# the fabrication isn't perfect but as a result, the wire isn't as# short as it could bexpts=(np.array(xpts)*anticrowding_factor).tolist()ifreverse:xpts=(-np.array(xpts)).tolist()start_width,end_width=end_width,start_widthD.info["num_squares"]=float(np.round(np.sum(np.diff(x_num_sq)/((y_num_sq[:-1]+y_num_sq[1:])/2)),3))D.add_polygon([xpts,ypts],layer=layer)xmin=min(xpts)xmin=snap_to_grid(xmin)xmax=max(xpts)xmax=snap_to_grid(xmax)ifnotsymmetric:D.add_port(name="e1",center=(xmin,start_width/2),width=start_width,orientation=180,layer=layer,)D.add_port(name="e2",center=(xmax,end_width/2),width=end_width,orientation=0,layer=layer,)ifsymmetric:D.add_port(name="e1",center=(xmin,0),width=start_width,orientation=180,layer=layer,)D.add_port(name="e2",center=(xmax,0),width=end_width,orientation=0,layer=layer,)returnD
if__name__=="__main__":c=optimal_step()# print(c.to_dict())# c = optimal_step()# print(c.to_dict())c.show(show_ports=True)c.assert_ports_on_grid()