Forum Replies Created

Viewing 20 posts - 41 through 60 (of 194 total)
  • Author
    Posts
  • in reply to: Euler bend pins extend further or inside waveguide #6437
    Ronald
    Keymaster

    Dear Lumico,

    You can add growy similar to growx, as described in this tutorial on xsections and layers.

    Ronald

    in reply to: Euler bend pins extend further or inside waveguide #6435
    Ronald
    Keymaster

    Dear Lumico,

    This is the same/similar effect as the snapping discussed in this post.
    The delta is in the order of the grid resolution or smaller.

    The simplest way to align the pin with the end line is to add a polygon point to the waveguide at the pin location. This is something that may be added to Nazca, mainly to avoid this visual misalignment (mostly harmless). Note this phenomena is not specific for the Euler bends but something that tends to show up for floating point positioning and subsequent snapping to a grid.

    The above is optically and process-technically mostly not an issue, but floating point rotations and/or translations in combination with hierarchical (gds) design can lead to (grid resolution) notches after flattening a design for mask manufacturing. In silicon photonics the DRC tends to be relatively unforgiven and it flags these notches (they can be waived, typically). The reason is that these DRC rules are based on previously existing “multiples of 90 deg” kind of geometries and not on photonic floating point geometry. In Nazca we created methods that force cells to ultimately snap polygons to the same top cell grid. These are not in the public Nazca release branch at present.

    Ronald

    in reply to: Finding the width of a pin #6428
    Ronald
    Keymaster

    Dear Jon,

    The properties dict works fine as you use it.

    Note that from Nazca >0.5.12 there will be a pin.radius attribute to store the radius directly in the pin. This also allows pin2pin DRC on connections, in addition to xs, width, angle and symmmetry checks.

    Ronald

    Ronald
    Keymaster

    Dear Tuhin,

    There are basically three loss factors in a bent waveguide:
    1- material loss
    2- sidewall (roughness) loss
    3- radiation loss

    The first two are also present in a straight guide. The extra loss in the bend is both an increase in (2), due to a higher field strength at the waveguide edge in a bend and (3). Both increase with smaller radii. To obtain (3) you need a complex (2D) modesolver that applies a conformal transformation to cylindrical coordinates. The complex index of the solution provides the bend loss. Hence, you need 2D bend solver, of which there are many, commercial ones like in VPI photonics, Lumerical or FIMwave, or open source solvers like in wgms3d.

    To get the loss in the bent guide a good approximation is to add the radiation loss to the known straight waveguide loss.

    Ronald

    in reply to: Show Pins outside the cell definition #6391
    Ronald
    Keymaster

    Dear Tommaso,

    Good to hear Nazca works well for you.

    In principle, a cell should not be changed after creation and there is no need for that. Note that the put_stub() does accept a list of pins, so if you only want to see pin ‘a0’, simply use nd.put_stub(['a0']), or nd.put_stub('a0'). But I think that’s what you use your boolean for that you mentioned, i.e. change that list of pins.

    That said, the stub/pin features discussed here are just a visualization of the pin, and the pin (Node object) actually already has a (sleeping) “show” attribute. It would not harm the cells fundamental features (like its connectivity) when changing the “show” after cell closure. It would quite straight forward to implement a cellA.showpins() method, and subsequently filter on the “show” attribute at time of mask export. It can actually be useful to clean up the layout view this way. Hence, I will add the lines for the next release (after 0.5.13).

    Ronald

    in reply to: Bending #6390
    Ronald
    Keymaster

    Dear Rose,

    If I copy paste the example with nd_export_plt() as provided and run in Spyder it shows the plot in the Spyder plot tab (Spyder4), as expected and shown in the post. If you do not see it, do you see any matplotlib output outside Nazca?

    If I copy paste the example and *replace* nd.export_plt(C) with nd.export_gds(C) it exports the gds as expected.

    Starting layout export...
    ...gds generation
    ...Wrote file './nazca_export.gds'

    Note-1

    nd_export_plt(C) # the C is needed as cell C is never put() in the example.
    # alternatively:
    C.put(0)
    nd_export_plt() # export the nazca main canvas having C on board.

    If you keep both plt and gds output commands you have to check the notes below.

    Note-2:

    nd_export_plt()  # deletes/resets the canvas after export
    nd_export_gds()  # nothing to draw

    Note-3:

    nd_export_plt(clear=False)  # does *not* delete the canvas
    nd_export_gds()  # now generates full gds

    Ronald

    in reply to: Bezier Curves with arbitrary number of points #6383
    Ronald
    Keymaster

    Dear Marios,

    Yes that will work, but as mentioned it needs the anglei and angleo keywords to be added to the Tp_Viper internally, which will now be in the new Nazca release (>0.5.12).

    For your information, the Viper internally only needs an override when angles are provided, like below. Angle “ab” carries through to a deeper polygon routine.

    if angleo is None:    
       ab = degrees(atan2( Y(1)-Y(1-d), X(1)-X(1-d)))  # angle of last semgent
    else:   
       ab = angleo

    Ronald

    in reply to: Bending #6380
    Ronald
    Keymaster

    Dear Rose,

    It generates a png as the one shown in the post.
    You may need to add a line like plt.show().
    (to poke Matplotlib, import matplotlob.pyplot as plt)

    For gds you can use nd.export_gds(C)

    Ronald

    in reply to: Bezier Curves with arbitrary number of points #6378
    Ronald
    Keymaster

    Dear Marios,

    The discretization may indeed lead to small polygon issues at the start and end points of a curve, as these angles are not exact when based in the last two points near an edge, if there is a curvature.

    This deviation can be avoided by providing the exact “input” and “output” angles of a curve. In the case of the Tp_viper() these should be optionally provided through keywords anglei and angleo, for the “input” and “output” of the curve, but these are not yet in the Viper keywords. I will add them (now always calculated inside the function before calling a deeper polygon function). Another way to improve the angle is to add a smaller last step in the Viper angle calculation, though this may suffer from numerical noise at some point. Yet another way is to extrapolate the curvature trend near the end an extrapolate that to the end point.

    Ronald

    PS
    Because you seem to have an input and output in the x-direction, you would simply have anglei=180, angleo=0 in your case.

    in reply to: Bending #6373
    Ronald
    Keymaster

    Dear Rose,

    To make a polygon shape follow an “arbitrary” line would require to transform its polygon from the standard straight coordinate system to one that follows the line. For an arc you can do something like below, where the red shape is the original shape and the blue is wrapped on a circular arc:

    from math import sin, cos
    import nazca as nd
    
    def create_taper():
        """Create a taper shape as you see fit."""
        dh = 1
        s = 30
        N = 20
        points1 = []
        points2 = []
        for i in range(N + 1):
            scale = -0.5 + i / N
            points1.append((s*scale, dh * (1 - abs(scale))))
            points2.append((-s*scale, -dh *(1 - abs(scale))))
        return points1 + points2                   
        
    def bend_polygon(points=None, radius=10):
        """Bend a polygon along a circular arc."""
        pointsout = []
        # Conformal transformation to a circular grid:
        for x, y in points:
            x2 = (radius + y) * sin(x / radius)
            y2 = (radius + y) * cos(x / radius)
            pointsout.append((x2, y2))
        return pointsout
        
    with nd.Cell() as C:
        radius = 15
        points = create_taper()
        pointsbend = bend_polygon(points=points, radius=radius)
        nd.Polygon(points=points, layer=1).put(0, radius)
        nd.Polygon(points=pointsbend, layer=2).put(0)
    
    nd.export_png(C)

    Ronald

    in reply to: Bending #6369
    Ronald
    Keymaster

    Dear Rose,

    Would you have a picture of what you like to achieve?

    Ronald

    in reply to: Hashme error #6353
    Ronald
    Keymaster

    Dear JHazan,

    The warning has been added to indicate that a second @hashme decorator has been activated before using the information generated by the first hashme in a with Cell() statement. Nazca warns now by raising an Exception. The hashme inspects the function it decorates and uses that to create a hash of call signature to add to the cell. That hash info is used in the first nd.Cell() call.

    You probably tried something like this

    import nazca as nd
    
    @nd.bb_util.hashme() # A
    def A():
        with nd.Cell():
            ...
    
    @nd.bb_util.hashme()
    def B():
        A()  # call A() which has a hashme, which deletes the B hash 
        with nd.Cell():  # B hash lost at this point
            ....

    The above overwrites the B hash due to the A call.
    Better is the following:

    @nd.bb_util.hashme()
    def A():
        with nd.Cell():
            ...
    
    @nd.bb_util.hashme()
    def B():
        with nd.Cell():  # use B hash before calling other hashed functions.
            A()
            ....

    Ronald

    in reply to: Connecting two cells within a cell #6302
    Ronald
    Keymaster

    Dear MirceaB,

    The cell instances c1 and c2 need to be connected in the scope of your cell ‘final’, not the pins inside the original cells. Pins inside cell1 and cell2 are indeed not in scope of cell ‘final’.

    Change the last line in cell ‘final’ to
    demofab.deep.cobra_p2p(pin1=cl1.pin['b0'], pin2=cl2.pin['a0']).put()

    Ronald

    in reply to: Photonic crystal line-defect waveguide – Remove holes #6292
    Ronald
    Keymaster

    Dear Dagi,

    If you makes cells of the holes, as in cell ‘hole’, the work would need to be done on the cell instances in your pxtal. This is possible via the cell_iter(), but here there may be a simpler solution by placing hole polygon objects directly in the pxtal cell. This is not something I have used before a lot, but you can scan and update directly on the polygon attribute in the cell object and filter it based on e.g. x-position of a hole, as demonstrated in the example below.
    I also added pins to make it a circuit type waveguide.

    import nazca as nd
    import numpy as np
    
    # Add layer
    nd.add_layer(name="ebeam", layer=1, overwrite=(True), fill_color=("red"))
    
    # Define PhC parameters
    hole_radius = 0.125
    PhC_ax = 0.425
    PhC_ay = 0.5 * PhC_ax * np.sqrt(3)
    hole_polygon = 20
    nx = 20
    ny = 10
    
    # Define hole shape and geometry
    hole_shape = nd.geometries.circle(radius=hole_radius, N=hole_polygon)
    hole1 = nd.Polygon(points=hole_shape, layer="ebeam")
    
    # ================================
    # make triangular lattice of holes
    # ================================
    with nd.Cell('pxtal', instantiate=False) as pxtal:
        hole_reference = []
        for ix in np.arange(-np.floor(nx / 2), np.floor(nx / 2)):
            for iy in np.arange(-np.floor(ny / 2), np.floor(ny / 2) + 1):
                x = (ix + np.mod(iy, 2) * 0.5) * PhC_ax
                y = iy * PhC_ay
                if ix != -np.floor(nx / 2) or np.mod(iy, 2) != 0:
                     hole1.put(x, y)
        nd.Pin('a0').put(0, 2, 90)
        nd.Pin('b0').put(0, -2, -90)
        nd.put_stub()
    
    # =============================
    # Add line-defect PhC waveguide
    # =============================
    pgons_new = []
    for pgon in pxtal.polygons:
        node, Poly = pgon
        x, y, a = node.xya()
        if abs(x) > 0.2:
            pgons_new.append((node, Poly))
    pxtal.polygons = pgons_new
    
    pxtal.put(0, 0, 90)
    
    # Export gds file
    nd.export_gds(filename="PhC.gds")

    Ronald

    in reply to: Procedure to create a flexible interconnect type #6280
    Ronald
    Keymaster

    Dear Jon,

    Would the free_form_curves approach work for your case?

    Ronald

    in reply to: Edge functions for a parallelogram? #6250
    Ronald
    Keymaster

    Dear lumico,

    A paralellogram function as you describe can be defined along these lines:

    def paralellogram(x=10, y=20, dy=None, y2=None):
        if y2 is None:
            y2 = y
        if dy is None:
            dy = 0.5 * (y - y2)
        return [(0, 0), (x, dy), (x, y2+dy), (0, y)]
        
    nd.Polygon(points=paralellogram(y2=2), layer=1).put()
    nd.Polygon(points=paralellogram(dy=1, y2=5), layer=1).put(15)
    
    nd.export_png()

    Ronald

    Ronald
    Keymaster

    Dear lumico,

    It seems the edge definition you used for the taper scales with t*length_1.
    Remove length_1 to make it indepent of the length as you need?

    Ronald

    in reply to: Select/delete objects in a cell with a size smallerthan x #6238
    Ronald
    Keymaster

    Dear Cameron,

    The best way to go about is to use the cell_iter(). It can dissect a Cell and rebuild it. This example shows an extended version where you can filter any cell element. In your case you can rebuild your gds but filter specific polygons, as indicated with the upper case remark:

    # Nazca-0.5.12
    import nazca as nd
    
    gds = 'your_file.gds'
    mask = nd.load_gds(gds)
    
    ly = nd.layout(layermap={}, layermapmode='all')
    
    for params in nd.cell_iter(mask):
        if params.cell_close:
            ly.close()
            continue
        if params.cell_create:
            ly.open(params=params)
        for pgon, xy, bbox in params.iters['polygon']:
            # xy and bbox coordinates are w.r.t. first instantiated parent
            
            # SELECT HERE WHICH POLYGONS YOU WANT TO ADD: 
            if < size of positions in xy > 5x5 >:
                ly.add_polygon(points=xy, layer=pgon.layer)
            else:
                print(f"polygon {xy} has been filtered out.")
        for pline, xy, bbox in params.iters['polyline']:
            # xy and bbox coordinates are w.r.t. first instantiated parent
            ly.add_polyline(points=xy, layer=pline.layer)
        for anno, pos in params.iters['annotation']:
            ly.add_annotation(text=anno.text, layer=anno.layer, pos=pos)
        for inode, [x, y, a], flip in params.iters['instance']:
            ly.add_instance(inode=inode, trans=[x, y, a], flip=flip)
    
    ly.put()
    nd.export_gds(filename=gds[:-4]+'_rebuild')

    If you know that your polygons that you want to filter are in a specific layer, you can use that too (I reversed the logic a bit compared to the example above):

    if pgon.layer == nd.get_layer(<layer>) and < size of positions in xy < 5x5 >:
        print(f"polygon {xy} has been filtered out.")
    else: 
        ly.add_polygon(points=xy, layer=pgon.layer)

    The get_layer() is to make sure you get the layer ID regardless if you use the layer numbers or layer names. pgon.layer contains the layer ID as well.

    Ronald

    in reply to: Issues with sbend_solve #6236
    Ronald
    Keymaster

    Dear iv_tern,

    Note that obj1 in pin2=obj1.pin['a0'] is not in scope of this snippet. If obj1 refers to an instance in another cell than you are working in you will get the “outside the scope” message. Note that obj1 should not be a Cell. Try type(obj1) to see what obj1 is.
    Can you reproduce this behaviour without the custom import?

    The nd.clear statements are better put directly after import nazca as nd
    Which Nazca version are you using?

    Ronald

    in reply to: Direction for building spiral Bragg gratings #6209
    Ronald
    Keymaster

    Dear Alex,

    Define a single polygon for the grating element and place that element repeatedly on the spine of the spiral waveguide curve at the right intervals. Would that work for your use case?

    Ronald

Viewing 20 posts - 41 through 60 (of 194 total)