Gated Quantum Dot

The aim of this tutorial is to demonstrate how the builder can be used to accelerate the generation of meshes appropriate for modelling semiconductor nanodevices. Here, the demonstration is made for the following gated quantum-dot system:

gated_dot

Fig. 16 gated_dot

The left-hand side of the above figure shows the layout for this example device, which can be found here. This layout file is in .gds format and can be visualized and modified using, e.g. KLayout. In the above picture, the red rectangle represents the simulation domain, while the blue rectangles represent metallic gates deposited on top of the chip that are used to control the confinement potential used to achieve confinement of single charge carriers in the x-y plane.

The right-hand side of the above figure illustrates the heterostructure stack, i.e., the multiple layers of materials used to confine charge carriers in the z direction. Each layer will be labeled differently to represent the role it plays in the heterostructure, and will be assigned a certain number of mesh layers depending on how accurate the simulation should be in each region. In this example, the mismatch between conduction band edges of GaAs and AlGaAs is used to form a Barrier isolating electrons in the substrate from the Cap region, and an n-doped layer is used to bend the conduction band edge and form a triangular confinement potential in the region indicated as 2DEG in the above figure. Finally, a Spacer region is used to isolate the quantum dot formed in the 2DEG from the dopants.

Setup

Constants

Next we define some constants that will be useful in setting up the device in the subsequent steps. All lengths are given in nanometers.

# Mesh characteristic lengths
char_len = 50  # Note that this is very low
dot_char_len = char_len / 2

# Thickness of each material layer
cap_thick = 10
barrier_thick = 15
dopant_thick = 5
spacer_thick = 5
two_deg_thick = 5
substrate_thick = 100 - two_deg_thick

Initialization

The Builder is based on the principle of taking a two dimensional shape and creating or editing three dimensional geometry through extrusion and etching, as well as using these shapes to define surfaces. Thus our first step will be to load an OASIS layout file with the two dimensional shapes we are going to use.

In order to do that, we initialize the instance and load the layout we are going to use. Each qtcad.builder.Builder instance corresponds to one Gmsh process and multiple instances can coexist. The layout can be imported as an OASIS file saved with the .oas extension. In this example we will load the gds file found gated_qd.oas. For example, in KLayout, this is done using File > Save As by selecting OASIS files in the drop-down menu 'Type' under the file name field.

builder = Builder(name="Quantum Dot").load_layout(
    save_dir / "layouts" / "gated_qd.oas", cell_name="builder"
)
[02:00:53 PM] INFO     Adding layer dot-region                                                                                                                masks.py:741
              INFO     Adding layer gates                                                                                                                     masks.py:741
              INFO     Adding layer footprint                                                                                                                 masks.py:741

In the constructor we provided a name for the model that we are going to create. Then we instructed the Builder to load the layout file. By default, all layers from the cell named qtcad.builder are loaded (see MaskContainer.load_layout for details). Each layer becomes a qtcad.builder.Mask mask object containing multiple qtcad.builder.Polygon objects. The shape names are read from the "name" user property. Alternatively, they can be set using text labels (as has been done in Advanced features). Using qtcad.builder.Builder.use_mask we will later select a particular mask. By default, this selects all shapes within that mask for subsequent operations. If we would like to be more specific, we can use qtcad.builder.Builder.use_shapes to select one or multiple shapes. The names of the physical surfaces and volumes that qtcad.builder.Builder creates are then derived from the names of the shapes. In general, the names of the physical groups are automatically generated base on the shape names (qtcad.builder.Builder.group_from_shape, if the shape has no name then one will be generated), on the name of the mask (qtcad.builder.Builder.group_from_mask) or on a given string (qtcad.builder.Builder.set_group_name). For extrusions, the base, top, and side surfaces will bear the name of the volume the bound with the suffixes "_base", "_top", and "_side", respectively.

Using qtcad.builder.Builder.print_mask_tree, we can print out the result of loading the layout file.

builder.print_mask_tree()
Layout
├── Mask 1 "dot-region"
│   └── 0  Polygon  "dot_region"
├── Mask 4 "gates"
│   ├── 0  Polygon  "top_gate_2"
│   ├── 1  Polygon  "top_gate_1"
│   ├── 2  Polygon  "bottom_gate_1"
│   ├── 3  Polygon  "bottom_gate_3"
│   ├── 4  Polygon  "bottom_gate_2"
│   └── 5  Polygon  "top_gate_3"
└── Mask 0 "footprint"
    └── 0  Polygon  "footprint"

<qtcad.builder.builder.Builder object at 0x7f17464fb890>

We can also view the shapes in the masks using qtcad.builder.Builder.view_shapes:

builder.use_mask("gates").view_shapes(save="out/layout_gates.svg", angles=(0, 0, 90))
gated qd
              INFO     Using mask 'gates'                                                                                                                   builder.py:750
              INFO     Viewing shapes: ['top_gate_2', 'top_gate_1', 'bottom_gate_1', 'bottom_gate_3', 'bottom_gate_2', 'top_gate_3'] using a temporary     builder.py:1922
                       builder instance

<qtcad.builder.builder.Builder object at 0x7f17464fb890>

In this case, we have loaded three Masks. The first contains the shapes that we will later use to define the electrostatic gate surfaces on the device. Second, the "footprint" mask contains a simple rectangle with the outline of the device. Lastly, the "dot-region" mask contains the outline of the region that we will later declare as the “dot-region” where no classical charges are allowed.

Creating the heterostructure

Now that we have loaded our layouts, we will define the create the basic layer structure of the device as shown in Fig. 16. In order to accomplish this, we will extrude the rectangle in the "footprint" mask.

The Builder (qtcad.builder.Builder) uses the builder pattern meaning that most operations are implemented as chained method calls. To create the heterostructure stack we then run the following code:

(
    builder.set_mesh_size(char_len)
    .set_min_elements(1)
    .use_mask("footprint")
    #
    # Substrate
    #
    .set_group_name("substrate")
    .extrude(substrate_thick)
    #
    # Electron confinement region
    #
    .set_group_name("two_deg")
    .extrude(two_deg_thick)
    #
    # Spacer
    #
    .set_group_name("spacer")
    .extrude(spacer_thick)
    #
    # Dopant
    #
    .set_group_name("dopant")
    .extrude(dopant_thick)
    #
    # Barrier
    #
    .set_group_name("barrier")
    .extrude(barrier_thick)
    #
    # Cap
    #
    .set_group_name("cap")
    .extrude(cap_thick)
)
[02:00:56 PM] INFO     Using mask 'footprint'                                                                                                               builder.py:750
              INFO     Extruding shape 0 from mask 'footprint' with name 'footprint' by 95 at z=0                                                          builder.py:2695
              INFO     Creating new physical group with name 'substrate_bottom'                                                                            builder.py:2482
              INFO     Creating new physical group with name 'substrate_side'                                                                              builder.py:2482
              INFO     Creating new physical group with name 'substrate_top'                                                                               builder.py:2482
              INFO     Creating new physical group with name 'substrate'                                                                                   builder.py:2482
              INFO     Setting z-coordinate to 95                                                                                                           builder.py:849
              INFO     Extruding shape 0 from mask 'footprint' with name 'footprint' by 5 at z=95                                                          builder.py:2695
              INFO     Creating new physical group with name 'two_deg_bottom'                                                                              builder.py:2482
              INFO     Creating new physical group with name 'two_deg_side'                                                                                builder.py:2482
              INFO     Creating new physical group with name 'two_deg_top'                                                                                 builder.py:2482
              INFO     Fragmenting...                                                                                                                    fragmenter.py:234
              INFO     Creating new physical group with name 'two_deg'                                                                                     builder.py:2482
              INFO     Setting z-coordinate to 100                                                                                                          builder.py:849
              INFO     Extruding shape 0 from mask 'footprint' with name 'footprint' by 5 at z=100                                                         builder.py:2695
              INFO     Creating new physical group with name 'spacer_bottom'                                                                               builder.py:2482
              INFO     Creating new physical group with name 'spacer_side'                                                                                 builder.py:2482
              INFO     Creating new physical group with name 'spacer_top'                                                                                  builder.py:2482
              INFO     Fragmenting...                                                                                                                    fragmenter.py:234
              INFO     Creating new physical group with name 'spacer'                                                                                      builder.py:2482
              INFO     Setting z-coordinate to 105                                                                                                          builder.py:849
              INFO     Extruding shape 0 from mask 'footprint' with name 'footprint' by 5 at z=105                                                         builder.py:2695
              INFO     Creating new physical group with name 'dopant_bottom'                                                                               builder.py:2482
              INFO     Creating new physical group with name 'dopant_side'                                                                                 builder.py:2482
              INFO     Creating new physical group with name 'dopant_top'                                                                                  builder.py:2482
              INFO     Fragmenting...                                                                                                                    fragmenter.py:234
[02:00:57 PM] INFO     Creating new physical group with name 'dopant'                                                                                      builder.py:2482
              INFO     Setting z-coordinate to 110                                                                                                          builder.py:849
              INFO     Extruding shape 0 from mask 'footprint' with name 'footprint' by 15 at z=110                                                        builder.py:2695
              INFO     Creating new physical group with name 'barrier_bottom'                                                                              builder.py:2482
              INFO     Creating new physical group with name 'barrier_side'                                                                                builder.py:2482
              INFO     Creating new physical group with name 'barrier_top'                                                                                 builder.py:2482
              INFO     Fragmenting...                                                                                                                    fragmenter.py:234
              INFO     Creating new physical group with name 'barrier'                                                                                     builder.py:2482
              INFO     Setting z-coordinate to 125                                                                                                          builder.py:849
              INFO     Extruding shape 0 from mask 'footprint' with name 'footprint' by 10 at z=125                                                        builder.py:2695
              INFO     Creating new physical group with name 'cap_bottom'                                                                                  builder.py:2482
              INFO     Creating new physical group with name 'cap_side'                                                                                    builder.py:2482
              INFO     Creating new physical group with name 'cap_top'                                                                                     builder.py:2482
              INFO     Fragmenting...                                                                                                                    fragmenter.py:234
              INFO     Creating new physical group with name 'cap'                                                                                         builder.py:2482
              INFO     Setting z-coordinate to 135                                                                                                          builder.py:849

<qtcad.builder.builder.Builder object at 0x7f17464fb890>

Above, wrapping the code in parenthesis allows to put the chained method calls on separate lines. In the second line we tell the Builder to use the characteristic length char_len when meshing the subsequently created volumes. Calling qtcad.builder.Builder.set_min_elements tells the Builder to ensure that there are will be at least two mesh cells along the narrowest dimension of the created entities (surfaces or volumes).

In the fourth line, we tell the Builder to use the mask named "footprint" for the upcoming operations. This will automatically select the only shape in this mask for the subsequent operations. Here, this is a simple rectangle with the appropriate dimensions (see Fig. 17).

gated_dot

Fig. 17 The footprint layout.

Subsequently, we save the current z coordinate for subsequent use. The z coordinate can be set with qtcad.builder.Builder.set_z_from_group or qtcad.builder.Builder.set_z_from_group and will be automatically advanced with each extrusion. Then, we tell builder to name the created surfaces/volumes based on the string "substrate" (rather than the name of the shape, see also Selection of shapes and naming modes) and extrude this shape by substrate_thick in line ten to create a volume named substrate__dg_vol. This process is then repeated with all subsequent layers. (Another way to change the name in this case would be to use qtcad.builder.Builder.rename_shape.)

At any point we can call qtcad.builder.Builder.view to open a Gmsh GUI window with the current model.

dg.view(True, volume_labels=True)

If we pass True as the first argument, the view process will pause the execution of the main process. Otherwise, execution will continue while the window is open. As can be seen below, each created volume derives it’s name from the name of the shape in the mask we set above. In this script we we use the save option to protduce an svg figure.

builder.view(
    surfaces=False,
    volume_labels=True,
    angles=(-90, 0, 85),
    save="out/heterostructure.svg",
    zoom=0.8,
)
gated qd
              INFO     Saving /home/hiro/Documents/org/roam/code/qtcad_flake/qtcad/packages/builder/examples/tutorials/out/heterostructure.svg             builder.py:1863

<qtcad.builder.builder.Builder object at 0x7f17464fb890>

Creating a dot region

The volume that will later be used to model the quantum features of the device will be a subregion of the total volume which has to be designated by its own physical groups. Furthermore, we typically desire a finer mesh in this region. In our case the dot region spans from the bottom of the substrate to the top of the spacer and will be created by simply extruding the first shape of the dot_region between the appropriate z coordinates.

To create the dot region we run the following:

dot_height = builder.get_z_from_group("spacer") - builder.get_z_from_group(
    "substrate", bottom=True
)
(
    builder.set_z_from_group("substrate", bottom=True)
    .overlay_mode()
    .set_mesh_size(dot_char_len)
    .minimum_mesh_size()
    .use_mask("dot-region")
    .group_from_shape()
    .extrude(dot_height)
)
[02:00:58 PM] INFO     Setting z-coordinate to 0.0                                                                                                          builder.py:849
              INFO     Using mask 'dot-region'                                                                                                              builder.py:750
              INFO     Extruding shape 0 from mask 'dot-region' with name 'dot_region' by 105.0 at z=0.0                                                   builder.py:2695
              INFO     Creating new physical group with name 'dot_region_bottom'                                                                           builder.py:2482
              INFO     Creating new physical group with name 'dot_region_side'                                                                             builder.py:2482
              INFO     Creating new physical group with name 'dot_region_top'                                                                              builder.py:2482
              INFO     Fragmenting...                                                                                                                    fragmenter.py:234
[02:01:00 PM] INFO     Creating new physical group with name 'two_deg.dot_region_side'                                                                     builder.py:2482
              INFO     Creating new physical group with name 'substrate.dot_region_side'                                                                   builder.py:2482
              INFO     Creating new physical group with name 'spacer.dot_region_side'                                                                      builder.py:2482
              INFO     Creating new physical group with name 'two_deg.dot_region'                                                                          builder.py:2482
              INFO     Creating new physical group with name 'spacer_bottom.dot_region'                                                                    builder.py:2482
              INFO     Creating new physical group with name 'two_deg_bottom.dot_region'                                                                   builder.py:2482
              INFO     Creating new physical group with name 'substrate.dot_region'                                                                        builder.py:2482
              INFO     Creating new physical group with name 'dopant_bottom.dot_region_top'                                                                builder.py:2482
              INFO     Creating new physical group with name 'spacer.dot_region'                                                                           builder.py:2482
              INFO     Creating new physical group with name 'substrate_bottom.dot_region_bottom'                                                          builder.py:2482
              INFO     Setting z-coordinate to 105.0                                                                                                        builder.py:849

<qtcad.builder.builder.Builder object at 0x7f17464fb890>

In line one we compute the total height of the dot region. We then set the Builder z-coordinate to the bottom of the substrate in line three. In line four, we switch the Builder to overlay mode, meaning that newly created volumes will be named according to the scheme [name of intersecting volume].[name of newly created volume] (see also qtcad.builder.FragmentationMode). This will allow us to disambiguate the different heterostructure layers of the dot region. Then we instruct the generator to take the minimum of the mesh size set with qtcad.builder.Builder.set_mesh_size using qtcad.builder.Builder.minimum_mesh_size and the mesh sizes already present in our heterostructure. Subsequently, we select the mask "dot-region" (see Fig. 18) and subsequently tell builder to derive the names of the created volume from the names of the shapes in the mask. Finally, we extrude the dot region.

../../../_images/dot_region.png

Fig. 18 The dot region layout.

Below we can see the result of these operations. Note that the part of the dot region intersecting with the substrate is called substrate.dot_region.

builder.view(
    surfaces=False,
    volume_labels=True,
    angles=(-82, 0, 90),
    save="out/model_dr.svg",
    zoom=2,
)
gated qd
              INFO     Saving /home/hiro/Documents/org/roam/code/qtcad_flake/qtcad/packages/builder/examples/tutorials/out/model_dr.svg                    builder.py:1863

<qtcad.builder.builder.Builder object at 0x7f17464fb890>

Adding the gate surfaces

Lastly, we add the surfaces that will be used to define the boundary conditions later on. These surfaces are the back gate at the bottom of the substrate and the control gates on the top of the device.

To add the surfaces we execute the following:

(
    #
    # Back Gate
    #
    builder.set_mesh_size(char_len)
    .use_mask("footprint")
    .use_shape("footprint")
    .displace_mode()
    .set_group_name("ohmic_bnd")
    .set_z_from_group("substrate", bottom=True)
    .add_surface()
    #
    # Control Gates
    #
    .use_mask("gates")
    .set_mesh_size(dot_char_len)
    .set_z_from_group("cap")
    .group_from_shape()
    .add_surface()
)
[02:01:01 PM] INFO     Using mask 'footprint'                                                                                                               builder.py:750
              INFO     Setting z-coordinate to 0.0                                                                                                          builder.py:849
              INFO     Creating a surface from shape 0 with name 'footprint' from mask 'footprint' at z=0.0                                                builder.py:2386
              INFO     Fragmenting...                                                                                                                    fragmenter.py:234
[02:01:02 PM] INFO     Creating new physical group with name 'ohmic_bnd'                                                                                   builder.py:2482
              INFO     Using mask 'gates'                                                                                                                   builder.py:750
              INFO     Setting z-coordinate to 135.0                                                                                                        builder.py:849
              INFO     Creating a surface from shape 0 with name 'top_gate_2' from mask 'gates' at z=135.0                                                 builder.py:2386
              INFO     Fragmenting...                                                                                                                    fragmenter.py:234
              INFO     Creating new physical group with name 'top_gate_2'                                                                                  builder.py:2482
              INFO     Creating a surface from shape 1 with name 'top_gate_1' from mask 'gates' at z=135.0                                                 builder.py:2386
              INFO     Fragmenting...                                                                                                                    fragmenter.py:234
              INFO     Creating new physical group with name 'top_gate_1'                                                                                  builder.py:2482
              INFO     Creating a surface from shape 2 with name 'bottom_gate_1' from mask 'gates' at z=135.0                                              builder.py:2386
              INFO     Fragmenting...                                                                                                                    fragmenter.py:234
              INFO     Creating new physical group with name 'bottom_gate_1'                                                                               builder.py:2482
              INFO     Creating a surface from shape 3 with name 'bottom_gate_3' from mask 'gates' at z=135.0                                              builder.py:2386
              INFO     Fragmenting...                                                                                                                    fragmenter.py:234
              INFO     Creating new physical group with name 'bottom_gate_3'                                                                               builder.py:2482
              INFO     Creating a surface from shape 4 with name 'bottom_gate_2' from mask 'gates' at z=135.0                                              builder.py:2386
              INFO     Fragmenting...                                                                                                                    fragmenter.py:234
[02:01:03 PM] INFO     Creating new physical group with name 'bottom_gate_2'                                                                               builder.py:2482
              INFO     Creating a surface from shape 5 with name 'top_gate_3' from mask 'gates' at z=135.0                                                 builder.py:2386
              INFO     Fragmenting...                                                                                                                    fragmenter.py:234
              INFO     Creating new physical group with name 'top_gate_3'                                                                                  builder.py:2482

<qtcad.builder.builder.Builder object at 0x7f17464fb890>

First, we select the coarser characteristic length and select the mask "footprint" as well as the the shape "footprint" within that mask (the mask now contains multiple shapes due to our copying and renaming while building the heterostructure). We then rename the selected shape create the back gate at the bottom. Subsequently we switch back to the displace_mode so that the names of the surfaces we create will be directly derived from the shape names (see also qtcad.builder.Builder.displace_mode). Finally we create the back gate surface the call to add_surface in line eight. Then, we use the the mask "gates" (see Fig. 19) to at the control gates at the bottom of the device. As we haven’t selected specific shapes within that mask, all shapes will be used at once to create the surfaces for the control gates.

../../../_images/layout_gates.png

Fig. 19 The gates layout.

../../../_images/user_prop.png

Fig. 20 The user property used to configure the names of shapes.

This results in the following (only showing the surfaces we just created):

builder.view(
    surface_labels=True,
    surfaces=True,
    angles=(-80, 0, 10),
    save="out/surfs.svg",
    zoom=0.8,
    groups=[
        "ohmic_bnd",
        "top_gate_1",
        "top_gate_2",
        "top_gate_3",
        "bottom_gate_1",
        "bottom_gate_2",
        "bottom_gate_3",
    ],
)
gated qd
              INFO     Saving /home/hiro/Documents/org/roam/code/qtcad_flake/qtcad/packages/builder/examples/tutorials/out/surfs.svg                       builder.py:1863

<qtcad.builder.builder.Builder object at 0x7f17464fb890>

We see, that each gate is named according to the name of the shape.

Meshing

Finally, we can save the mesh generated from the instructions above to the disk using the qtcad.builder.Builder.mesh method:

builder.mesh(3, algorithm3d=MeshAlgorithm3D.HXT, show_gmsh_output=True).write(
    save_dir / "meshes/gated_dot.msh"
)
[02:01:04 PM] INFO     Preparing to mesh                                                                                                                   builder.py:1502
              INFO     Detecting appropriate random factor                                                                                                 builder.py:3608
[02:01:07 PM] INFO     Increased random factor from 1e-09 to 2.0402335012609454e-07                                                                        builder.py:3626
[02:01:10 PM] INFO     Random factor is now appropriate                                                                                                    builder.py:3632
              INFO     Meshing                                                                                                                             builder.py:1518
/home/hiro/Documents/org/roam/code/qtcad_flake/qtcad/packages/builder/src/qtcad/builder/core/util/decorators.py:32: UserWarning: Encountered disconnected volumes: 3D Meshing 9 volumes with 2 connected components
  return func(self, *args, **kwargs)
[02:02:20 PM] INFO     Checking mesh conformity                                                                                                            builder.py:3688
              INFO     Writing /tmp/tmp8a1mwig3/mesh.msh                                                                                                   builder.py:1604
[02:02:28 PM] INFO     Checking connectivity                                                                                                               builder.py:3715

nodes:   0%|          | 0/82341 [00:00<?, ?it/s]
nodes:   0%|          | 0/82341 [00:00<?, ?it/s]
nodes: 100%|██████████| 82341/82341 [00:00<00:00, 7228044.32it/s]
nodes: 100%|██████████| 82341/82341 [00:00<00:00, 7056004.28it/s]
nodes: 100%|██████████| 82341/82341 [00:00<00:00, 6966619.31it/s]
[02:02:29 PM] INFO     Writing /home/hiro/Documents/org/roam/code/qtcad_flake/qtcad/packages/builder/examples/tutorials/meshes/gated_dot.msh               builder.py:1604

<qtcad.builder.builder.Builder object at 0x7f17464fb890>

Here the first argument sets the meshing dimension and the save input gives the path and name of the output mesh we wish to save. By default, the output mesh will not be saved. However here we have specified that the output mesh should be saved to the meshes/ directory under the name gated_dot.msh. We refer to qtcad.builder.Builder.mesh for further details.

The resulting mesh is shown below. Note how thinner layers use smaller mesh-sizes, as does the dot-region.

builder.view(
    surfaces=False,
    volume_labels=True,
    angles=(-90, 0, 85),
    save="out/mesh.png",
)

builder.view(
    surfaces=False,
    volume_labels=True,
    angles=(-90, 0, 85),
    save="out/mesh_dr.png",
    groups=["substrate.dot_region", "two_deg.dot_region", "spacer.dot_region"],
)
gated qd
gated qd
              INFO     Saving /home/hiro/Documents/org/roam/code/qtcad_flake/qtcad/packages/builder/examples/tutorials/out/mesh.png                        builder.py:1863
[02:02:32 PM] INFO     Saving /home/hiro/Documents/org/roam/code/qtcad_flake/qtcad/packages/builder/examples/tutorials/out/mesh_dr.png                     builder.py:1863

<qtcad.builder.builder.Builder object at 0x7f17464fb890>

Total running time of the script: (1 minutes 44.528 seconds)

Gallery generated by Sphinx-Gallery