Tagged: pcurve, dumplayer, radius DRC, minimum radius, viper, cobra_p2p
 This topic has 8 replies, 2 voices, and was last updated 4 years, 11 months ago by Ronald.

AuthorPosts

29 October 2018 at 12:12 #5241DouglasParticipant
Hey all,
Another one: is there a way to make a pcurve_p2p tapered?
I would need this p2p bend to connect waveguides with different widths.
Ah, in addition I see that the generated GDS uses not only layer 10, but also layer 1111. Wht would be the reasoning of it? Is there a way to not see this additional layer?import nazca as nd # Define interconnect myIC = nd.interconnects.Interconnect(radius=10, width=0.49, layer=10) # Defining bends InBend = myIC.bend(angle=40,width=0.450).put(0,0) OutStr = myIC.strt(length=10).put(70,0) myIC.pcurve_p2p(InBend.pin['b0'], OutStr.pin['a0'], Rin=30, Rout=30).put() nd.export_gds(filename='issue2.gds')
Thanks,
Doug
1 November 2018 at 12:29 #5247RonaldKeymasterDear Douglas,
The pcurve is a specific type of parametric curve, but the methodology used for the pcurve can be extended to other kinds of parametric curves, e.g. a tapered one. It needs a tutorial in the near future.
As for the “Ah, in addition” part:
GDS layer (1111, 0) is a “dumplayer”. If you use an unknown layer in Nazca, your output will be redirected to the dumplayer to show you some layer definition needs fixing.Ronald
5 November 2018 at 16:24 #5255DouglasParticipantGreat,
Thanks. Am trying to work on that by creating a modified version of theÂ polyline2polygon function on my own piece of code. Let you know if I find some problems, or if it takes longer than expected.
Another thing, maybe this would better be in another topic, but will post here anyhow: By using the pcurve I am getting this warning.
Warning: DRC minimum_radius 26.226 < 100000000.000
I saw on the mask_elements.py file that you are looking for aÂ minimum_radius key on the cross section dictionary, but I see no way to set that key. Is this an open task for you guys?
Thanks,
Doug
5 November 2018 at 16:47 #5256RonaldKeymasterDear Douglas,
If a xsection has the ‘minimum_radius’ defined then pcurve will use it.
If a xsection does not have the ‘minimum_radius’, then a minimum of 0 is used, effectively taking down the radius check.An example to set or update the xsection minimum radius to 100 um looks as follows:
import nazca as nd xs = nd.get_xsection(<xsection_name_string>) # get the xsection object if you know its name. xs.minimum_radius = 100
where ‘xsection_name_string’ should be replaced by an existing xsection name.
Ronald
5 November 2018 at 17:09 #5257DouglasParticipantAh, great! Thanks again.
This will be useful for my nontapered bents, since the tapered ones will be using the modified polyline2polygon method.
Cheers,
Doug
5 November 2018 at 17:56 #5258DouglasParticipantAnd here comes a big code…
I managed to reuse your polyline2polygon in a brute force way.
Solved my problem for some cases, but not for all.
On my code I see some spurious points in the beginning of the bent taper.
Would you know why, and mainly, how to solve that?Thanks
import nazca as nd import nazca.generic_bend as gb import nazca.util as util def polyline2polygonTapered(xy, widthIn=0.49, widthOut=0.49, miter=0.5): """Return a polygon that contains the outline points of a tapered polyline Since we have to specify the outline of two or more segments that make an angle, we have to know what to do with the gap between those segments at the outside of the corner. In order to determine which points are on the outside of the corner we use the following algorithm: Given a line segment between P0 (x0,y0) and P1 (x1,y1), another point P (x,y) has the following relationship to the line segment. Compute (y  y0) (x1  x0)  (x  x0) (y1  y0). If it is less than 0 then P is to the right of the line segment, if greater than 0 it is to the left, if equal to 0 then it lies on the line segment. The routine fills an array from the start with the anticlockwise points and from the end with the clockwise points. Args: xy (list): list of (x,y) points that hold the polygon width (float): width of the polyline (default 2) miter (float): maximum fraction of the width before an extra point is added in outside corners (default 0.5) Returns: list of (float, float): the polygon """ # the fraction of the width of the line segments that is used to # determine if a single point is sufficient to describe the outline, or # that two points are needed (miter limit). dsqrmax = (miter * widthIn)**2 n = len(xy) if n < 2: raise ValueError("Polyline2polygon: need at least 2 points for polyline.") # Compute array of widths widths = [] for i in range(len(xy)): widths.append(widthIn+(widthOutwidthIn)/(len(xy)+1)*(i+1)) # Start with the first two points dxy1 = util.pointdxdy(xy, 0, widths[0]) cxy1 = util.corner(xy, 0, dxy1) xy_start = [cxy1[0]] xy_end = [cxy1[1]] for i in range(1, n1): # loop over the points in the polyline dxy0 = dxy1 # Shift corner points from next to current segment. cxy0 = cxy1 # Get corner points for next segment. dxy1 = util.pointdxdy(xy, i, widths[i+1]) cxy1 = util.corner(xy, i, dxy1) # left or right turn lrt = (xy[i+1][1]xy[i1][1]) * (xy[i][0]xy[i1][0]) \ (xy[i+1][0]xy[i1][0]) * (xy[i][1]xy[i1][1]) # Distance (squared) between the two points at the kink (2>4 == 3>5) dsqr = (cxy1[0][0]  cxy0[2][0])**2 + (cxy1[0][1]  cxy0[2][1])**2 # the inside corner point is on the intersection of the two inside # lines. if lrt > 0: # Left turn # Outside corner: use two points, unless these points are close. if dsqr < dsqrmax: xy_start.append(util.intersect(cxy0[0], cxy0[2], cxy1[0], cxy1[2])) else: xy_start.append((xy[i][0]+dxy0[0], xy[i][1]+dxy0[1])) xy_start.append((xy[i][0]+dxy1[0], xy[i][1]+dxy1[1])) # Inside corner: always intersect. xy_end.append(util.intersect(cxy0[1], cxy0[3], cxy1[1], cxy1[3])) elif lrt < 0: # Right turn # Outside corner: use two points, unless these points are close. if dsqr < dsqrmax: xy_end.append(util.intersect(cxy0[1], cxy0[3], cxy1[1], cxy1[3])) else: xy_end.append((xy[i][0]dxy0[0], xy[i][1]dxy0[1])) xy_end.append((xy[i][0]dxy1[0], xy[i][1]dxy1[1])) # Inside corner: always intersect. xy_start.append(util.intersect(cxy0[0], cxy0[2], cxy1[0], cxy1[2])) else: continue # No turn: goto next point # Last two points. xy_start.append(cxy1[2]) xy_end.append(cxy1[3]) return xy_start + list(reversed(xy_end)) ######## # Actual testing code ######## # Define interconnect nd.add_layer2xsection(xsection='WgXS', layer=10, accuracy=0.001) myIC = nd.interconnects.Interconnect(radius=10, width=0.49, xs='WgXS') # TESTING THE TAPERED BEND  From bend to str # Defining bends InBend = myIC.bend(angle=50,radius=8.5,width=0.450).put(0,0) OutStr = myIC.strt(length=10).put(70,0) xya = nd.diff(InBend.pin['b0'],OutStr.pin['a0'].rot(180)) A, B, L ,Rmin = gb.gb_coefficients(xya,Rin=30, Rout=30) # Curve parameters xy = gb.curve2polyline(gb.gb_point, xya, 0.001, (A, B, L)) # Curve points xy = polyline2polygonTapered(xy,widthIn=0.45,widthOut=0.49) nd.Polygon(layer=10, points=xy).put(InBend.pin['b0']) # TESTING THE TAPERED BEND  From bend to str with initial radius not as desired # Defining bends InStr = myIC.strt(length=10).put(0,18) OutBend = myIC.bend(angle=50,radius=8.5,width=0.450).put(70,15,50) xya = nd.diff(InStr.pin['b0'],OutBend.pin['a0'].rot(180)) A, B, L ,Rmin = gb.gb_coefficients(xya,Rin=30,Rout=30) # Curve parameters xy = gb.curve2polyline(gb.gb_point, xya, 0.001, (A, B, L)) # Curve points xy = polyline2polygonTapered(xy,widthIn=0.49,widthOut=0.45) nd.Polygon(layer=10, points=xy).put(InStr.pin['b0']) # TESTING THE TAPERED BEND  From bend to str  with desired initial radius # Defining bends InStr = myIC.strt(length=10).put(0,36) OutBend = myIC.bend(angle=50,radius=8.5,width=0.450).put(70,33,50) xya = nd.diff(InStr.pin['b0'],OutBend.pin['a0'].rot(180)) A, B, L ,Rmin = gb.gb_coefficients(xya,Rin=30,Rout=30) # Curve parameters xy = gb.curve2polyline(gb.gb_point, xya, 0.001, (A, B, L)) # Curve points xy = polyline2polygonTapered(xy,widthIn=0.49,widthOut=0.45) nd.Polygon(layer=10, points=xy).put(InStr.pin['b0']) nd.export_gds(filename='issue3.gds')
15 November 2018 at 10:01 #5275RonaldKeymasterDear Douglas,
I see the points popping out for your new function (top curve in picture below):
xy = polyline2polygonTapered(xy, widthIn=0.49, widthOut=0.49)
If I use the original Nazca function everything looks fine (bottom curve):
xy = nd.util.polyline2polygon(xy, width=0.49)
Note I use the same width 0.49 everywhere.
Hence, you would have to check why your updated function behaves differently for the same parameter settings.
For the bottom curve for normal usage it is advised, and much simpler, to use the pcurve() interconnect and not the underlying polyline2polygon.
Ronald
13 July 2019 at 19:08 #5635RonaldKeymasterHi Douglas,
Note that since Nazca0.5.1 there is the viper() method:
and since Nazca0.5.2 also a cobra_p2p() interconnect with tapering functionality.
Ronald
8 December 2019 at 22:50 #5904RonaldKeymasterDear Douglas,
The viper has been integrated as a mask element in nazca 0.5.8.
This tutorial may be of use: Free form curves
Ronald

AuthorPosts
 You must be logged in to reply to this topic.