Shapes and generic cells#

gdsfactory provides some generic parametric cells in gf.components that you can customize for your application.

Basic shapes#

Rectangle#

To create a simple rectangle, there are two functions:

gf.components.rectangle() can create a basic rectangle:

import gdsfactory as gf

r1 = gf.components.rectangle(size=(4.5, 2), layer=(1, 0))
r1.plot()
../_images/92e502b004e81116ab25fee0076ee94d0ee7afcc38c010c19e9cf140a6ef9d34.png

gf.components.bbox() can also create a rectangle based on a bounding box. This is useful if you want to create a rectangle which precisely surrounds a piece of existing geometry. For example, if we have an arc geometry and we want to define a box around it, we can use gf.components.bbox():

c = gf.Component()
arc = c << gf.components.bend_circular(radius=10, width=0.5, angle=90, layer=(1, 0))
arc.rotate(90)

# Draw a rectangle around the arc we created by using the arc's bounding box.
rect = c << gf.components.bbox(arc, layer=(2, 0))
c.plot()
../_images/00f5afd0786a8c4a105d3ec3bc4b897628917432947ad63200d8e24fe80b64fc.png

Cross#

The gf.components.cross() function creates a cross structure:

c = gf.components.cross(length=10, width=0.5, layer=(1, 0))
c.plot()
../_images/6e2242faee5e3df8b001b0a725c9c05a8686bdadbc0338bf35d592bba70cc0ee.png

Ellipse#

The gf.components.ellipse() function creates an ellipse by defining the major and minor radii:

c = gf.components.ellipse(radii=(10, 5), angle_resolution=2.5, layer=(1, 0))
c.plot()
../_images/107107d09a9b226cbcb80227e1f5262ebe64541e70954e021c49240ed2276c10.png

Circle#

The gf.components.circle() function creates a circle:

c = gf.components.circle(radius=10, angle_resolution=2.5, layer=(1, 0))
c.plot()
../_images/2857f1a04fba3d9ce62d4585854d3f5d8b0acae704663b703af17b4b03c0e41b.png

Ring#

The gf.components.ring() function creates a ring. The radius refers to the center radius of the ring structure (halfway between the inner and outer radius).

c = gf.components.ring(radius=5, width=0.5, angle_resolution=2.5, layer=(1, 0))
c.plot()
../_images/e847d9a1db2a76839f8d437bd73772f28364acbcee02be1e2f6e51cabc8955b0.png
c = gf.components.ring_single(gap=0.2, radius=10, length_x=4, length_y=2)
c.plot()
../_images/ee17377155f36bd9725fbce9a3b7bcc5651494ce17273b122543e601f77acaf2.png
import gdsfactory as gf

c = gf.components.ring_double(gap=0.2, radius=10, length_x=4, length_y=2)
c.plot()
../_images/aa78420fd09f4e1ab9cac3d89a6281863a299205fa7ebce863ec6a986804c6b7.png
c = gf.components.ring_double(
    gap=0.2,
    radius=10,
    length_x=4,
    length_y=2,
    bend=gf.components.bend_circular,
)
c.plot()
../_images/d9b85d64068fbee8b65d6f139c51b2294c0c5a7c4b756c7fdcbe91ba1082bbf1.png

Bend circular#

The gf.components.bend_circular() function creates an arc. The radius refers to the center radius of the arc (halfway between the inner and outer radius).

c = gf.components.bend_circular(
    radius=5.0, width=0.5, angle=90, npoints=720, layer=(1, 0)
)
c.plot()
../_images/14465f26e1c66dd607515ac72b42d4efbeac23418fdb4303e88deea611bdfefb.png

Bend euler#

The gf.components.bend_euler() function creates an adiabatic bend in which the bend radius changes gradually. Euler bends have lower loss than circular bends.

c = gf.components.bend_euler(radius=5.0, width=0.5, angle=90, npoints=720, layer=(1, 0))
c.plot()
../_images/c393b99557ff3add31412b1287be0b055c7851545f98797944a5363694cbc4fd.png

Tapers#

gf.components.taper()is defined by setting its length as well as its start and end length. It has two ports, 1 and 2, on either end, allowing you to easily connect it to other structures.

c = gf.components.taper(length=10, width1=6, width2=4, port=None, layer=(1, 0))
c.plot()
../_images/f1b4203e2af58102bfb5676260235b30a03d58dfdd4d974f0d236188df95e3a7.png

gf.components.ramp() is a structure is similar to taper() except it is asymmetric. It also has two ports, 1 and 2, on either end.

c = gf.components.ramp(length=10, width1=4, width2=8, layer=(1, 0))
c.plot()
../_images/178782ceefb754e8840a9d710f309e7fc3921bb8e83ad97b6084904360c53218.png

Common compound shapes#

The gf.components.L() function creates a “L” shape with ports on either end named 1 and 2.

c = gf.components.L(width=7, size=(10, 20), layer=(1, 0))
c.plot()
../_images/48eb8f1552c4468354f53224a4d8e7912af046ddb787acaf91566b434f3bf9a9.png

The gf.components.C() function creates a “C” shape with ports on either end named 1 and 2.

c = gf.components.C(width=7, size=(10, 20), layer=(1, 0))
c.plot()
../_images/406d62744dbbd585afb86beb9a2b573edb6d7c544bf83faa8dd4b70a2f5c6ce6.png

Text#

Gdsfactory has an implementation of the DEPLOF font with the majority of english ASCII characters represented (thanks to PHIDL)

c = gf.components.text(
    text="Hello world!\nMultiline text\nLeft-justified",
    size=10,
    justify="left",
    layer=(1, 0),
)
c.plot()
# The justify parameter needs to be 'left', 'center', or 'right',
# because those are the standard text alignment options that determine how multiple lines of text are positioned relative to each other.
../_images/8783c2d97bc05c6bada491bfeae911c4a75d705861035088481f114b6175e6c5.png

Lithography Structures#

Step-resolution#

The gf.components.litho_steps() function creates a lithographic test structure that is useful for measuring the resolution of photoresist or electron-beam resists. It provides both positive-tone and negative-tone resolution tests.

c = gf.components.litho_steps(
    line_widths=(1, 2, 4, 8, 16), line_spacing=10, height=100, layer=(1, 0)
)
c.plot()
../_images/2f38c0995840b006533ebee15d401875d52c11f614068c51e703a726de107f08.png

Calipers (inter-layer alignment)#

The gf.components.litho_calipers() function is used to detect offsets in multilayer fabrications. It creates a set of two notches on different layers. When a fabrication error/offset occurs, it is easy to detect the magnitude of the offset because both center-notches are no longer aligned.

D = gf.components.litho_calipers(
    notch_size=(1, 5),
    notch_spacing=2,
    num_notches=7,
    offset_per_notch=0.1,
    row_spacing=0,
    layer1=(1, 0),
    layer2=(2, 0),
)
D.plot()
../_images/b07cb8f7c9c177ec04c4d5f00c0b220c4b835aeba4502882c39bcb34ab686488.png

Paths#

See Path tutorial for more details – this is just an enumeration of the available built-in Path functions

Circular arc#

P = gf.path.arc(radius=10, angle=135, npoints=720)
f = P.plot()
../_images/59662a9b83acc46ae489b66aac53e9ccba12795a701d87700ed0b2dac88a4092.png

Straight#

import gdsfactory as gf

P = gf.path.straight(length=5, npoints=100)
f = P.plot()
../_images/df601fe00e2cf09e3d5172cf8878a789ab602cffdfe610f890f9581a4a1d5911.png

Euler curve#

Also known as a straight-to-bend, clothoid, racetrack, or track transition, this path tapers adiabatically from straight to curved. Often used to minimize losses in photonic straights. If p < 1.0, it will create a “partial euler” curve as described in Vogelbacher et. al. https://dx.doi.org/10.1364/oe.27.031394.
If the use_eff argument is false, radius corresponds to minimum radius of curvature of the bend. If use_eff is true, radius corresponds to the “effective” radius of the bend– The curve will be scaled such that the endpoints match an arc with parameters radius and angle.

P = gf.path.euler(radius=3, angle=90, p=1.0, use_eff=False, npoints=720)
f = P.plot()
../_images/e8d00b84f1f3736ac4274e561eed3ae2afa65233a4e65c9fd1cb121958990b5f.png

Smooth path from waypoints#

import numpy as np

import gdsfactory as gf

points = np.array([(20, 10), (40, 10), (20, 40), (50, 40), (50, 20), (70, 20)])

P = gf.path.smooth(
    points=points,
    radius=2,
    bend=gf.path.euler,
    use_eff=False,
)
f = P.plot()
../_images/c771b16e8505ce25db8c933e50cf0d1e921f330cf736ada005283ceafc02d5db.png

Delay spiral#

A delay spiral is a long optical waveguide coiled into a spiral shape on a photonic integrated circuit. Its purpose is to create a significant time delay for an optical signal within a very compact area.

c = gf.components.spiral_double()
c.plot()
../_images/44cac7b6ca6cd74c95b360e329b360c319d3cad0a1cf44501391d1dbb48e4826.png
c = gf.components.spiral()
c.plot()
../_images/237432d589725dc75c2f5543f4b5237b6c4784af1ef8f464139aa13a897a0263.png
c = gf.components.spiral_racetrack_fixed_length()
c.plot()
/home/runner/work/gdsfactory/gdsfactory/gdsfactory/components/bends/bend_circular.py:86: UserWarning: {'width': 0.5} ignored for cross_section 'strip'
  x = gf.get_cross_section(cross_section, width=width or x.width)
../_images/c456e99ef54eed85321596c0e595a5baf40d40ced6d12e246975c0e3f9a8dfd2.png

Useful contact pads / connectors#

These functions are common shapes with ports, often used to make contact pads.

c = gf.components.compass(size=(4, 2), layer=(1, 0))
c.plot()
../_images/f645878100677c05626af21d83ba3d641412f2ccefc5a982c4da0845d75e2f53.png
c = gf.components.nxn(north=3, south=4, east=0, west=0)
c.plot()
../_images/19b0cb6fd6fb4f6c6c948521fc9e211ef569091be4dbd48945ff98f21ab3975a.png
c = gf.components.pad()
c.plot()
../_images/449018b5d6ceb65517dc5c4987972c3600e64ad33c4c191dae2f263cdf0050bc.png
c = gf.components.pad_array90(columns=3)
c.plot()
../_images/fae0198974b9f30fa74025e57a3b4d59a3a0853828e7ffc8701b336282d7edb8.png

Chip / die template#

import gdsfactory as gf

c = gf.components.die(
    size=(10000, 5000),  # Size of the die.
    street_width=100,  # Width of corner marks for die-sawing.
    street_length=1000,  # Length of corner marks for die-sawing.
    die_name="chip99",  # Label text.
    text_size=500,  # Label text size.
    text_location="SW",  # Label text compass location e.g. 'S', 'SE', 'SW'
    layer=(2, 0),
    bbox_layer=(3, 0),
)
c.plot()
../_images/539c970c406347d3e8a877e98e864b01c79b1748d3a206bd47c5aaf889bcf669.png

Optimal superconducting curves#

The following structures are meant to reduce “current crowding” in superconducting thin-film structures (such as superconducting nanowires). They are the result of conformal mapping equations derived in Clem, J. & Berggren, K. “Geometry-dependent critical currents in superconducting nanocircuits.” Phys. Rev. B 84, 1–27 (2011).

import gdsfactory as gf

# This code creates a compact, U-shaped "hairpin" delay line with bends that are optimized for low loss.
c = gf.components.optimal_hairpin(
    width=0.2, pitch=0.6, length=10, turn_ratio=4, num_pts=50, layer=(2, 0)
)
c.plot()
../_images/417ed66fb332f692f41da11a8ea200aacce94e09b4f7e0f2a220560ae5f0f0fa.png
# This code creates a taper, which is a waveguide section that smoothly transitions between two different widths.
# The optimal_step component is special because its shape is mathematically optimized to be adiabatic, minimizing light loss and back-reflections.
c = gf.components.optimal_step(
    start_width=10, # Defines the initial width of the taper.
    end_width=22, # Defines the final width of the taper.

    # num_pts=50: This sets the number of points used to define the optimized S-curve. A higher number results in a smoother, more finely detailed curve.
    num_pts=50,

    # This is the width tolerance. It defines how close the optimization algorithm must get to the target end_width.
    # A smaller value results in a more precise, but potentially longer, taper.
    width_tol=1e-3,

    # This factor adjusts the "aggressiveness" of the S-curve.
    # A larger value creates a more gradual, less crowded transition at the start and end of the taper.
    anticrowding_factor=1.2,

    # This parameter creates a one-sided taper. One edge of the taper will be a straight line, while the other will have the optimized S-curve.
    # If True, both sides would curve symmetrically.
    symmetric=False,
    layer=(2, 0),
)
c.plot()
../_images/b01c8ecd3d51f7abe362cdb6396c50c06d0a4390d2c57ac5f736211019c4a27d.png
c = gf.components.optimal_90deg(width=100.0, num_pts=15, length_adjust=1, layer=(2, 0))
c.plot()
../_images/c7168ddd66806b957256430b6da623fd404147adb7233d1b7351ce4c4dc9f55b.png
# This code creates a Superconducting Nanowire Single-Photon Detector (SNSPD), a specialized component designed to detect single photons of light.
c = gf.components.snspd(
    wire_width=0.2,
    wire_pitch=0.6,
    size=(10, 8), # The overall dimensions of the meandered detector area are 10x8 µm.
    num_squares=None, # num_squares=None means that the size of the component is being defined by the size parameter.
    turn_ratio=4, # Controls the shape of the 180-degree bends in the meander(Clojure/Clojurescript library).
    terminals_same_side=False, # The input and output terminals will be on opposite sides of the detector.
    layer=(2, 0),
)
c.plot()
../_images/7088cac6b67820357fc0c0b37685ff8f1749d329846676c45b9fddf8fa7cca88.png

Generic library#

gdsfactory comes with a generic library that you can customize to your needs or even modify the internal code to create the components that you need.