2. Creating the FD-SOI Device

2.1. Requirements

2.1.1. Software components

  • QTCAD

2.1.2. Python script

  • qtcad/examples/practical_application/FDSOI/double_dot_fdsoi.py

2.1.3. References

2.2. Briefing

The file presented in this section is not meant to be run. Instead, it contains quantities and a function that are imported by other scripts in this practical application tutorial series. In particular, the function get_double_dot_fdsoi defined here is used to create the FD-SOI Device object. This function is analogous to the identically named function defined in A double quantum dot device in a fully-depleted silicon-on-insulator transistor.

2.4. Default values

We then define some default values that will be used in the different scripts.

# Default values
V_set       = 1.25              # Default SET potential (V)
V_qubit     = 0.75              # Default qubit potential (V)
scaling     = 1e-9              # scaling factor for the mesh

These provide the default voltages to be applied to the single-electron transistor (SET) and qubit gates (plunger_gate_1_bnd and plunger_gate_2_bnd, respectively) and also define the length scale of the mesh.

2.6. Creating the device

Finally, we define the function that creates and returns the FD-SOI device model.

# Function to create the FD-SOI device
def get_double_dot_fdsoi(mesh_file_name: str="refined_dqdfdsoi.msh",
                        V_set: float=V_set, V_qubit: float=V_qubit) -> Device:
    """Create a Device object for the FD-SOI structure.

    Args:
        V_set (float): Potential applied to the SET gate.
        V_qubit (float): Potential applied to the qubit gate.
        mesh_file_name (str): Filename of the mesh file.

    Returns:
        Device: The constructed Device object.
        list[str]: List of region names associated with the SET.
        list[str]: List of region names associated with the qubit quantum-dot.
    """
    # Create the mesh
    script_dir           = pathlib.Path(__file__).parent.resolve()
    path_mesh            = script_dir / "meshes"
    mesh_file            = path_mesh / mesh_file_name
    mesh                 = Mesh(scaling, mesh_file)

    # Define the device object
    dvc = Device(mesh, conf_carriers='e')
    dvc.set_temperature(0.1)

    # Create the regions
    dvc.new_region("oxide", mt.SiO2)
    dvc.new_region("oxide.QD1", mt.SiO2)
    dvc.new_region("oxide.QD2", mt.SiO2)
    dvc.new_region("channel", mt.Si)
    dvc.new_region("channel.QD1", mt.Si)
    dvc.new_region("channel.QD2", mt.Si)
    dvc.new_region("source", mt.Si, ndoping=1e20*1e6)
    dvc.new_region("drain", mt.Si, ndoping=1e20*1e6)

    # Set up boundary conditions
    Ew = mt.Si.Eg/2 + mt.Si.chi # Midgap
    dvc.new_gate_bnd("barrier_gate_1_bnd", 0.5, Ew)
    dvc.new_gate_bnd("plunger_gate_1_bnd", V_set, Ew)
    dvc.new_gate_bnd("barrier_gate_2_bnd", 0.5, Ew)
    dvc.new_gate_bnd("plunger_gate_2_bnd", V_qubit, Ew)
    dvc.new_gate_bnd("barrier_gate_3_bnd", 0.5, Ew)
    dvc.new_ohmic_bnd("source_bnd")
    dvc.new_ohmic_bnd("drain_bnd")
    dvc.new_frozen_bnd("back_gate_bnd", -0.5, mt.Si, 1e15*1e6,
        "n", 46*1e-3*ct.e)

    # Create the double quantum dot region
    SET_region_list = ["oxide.QD1", "channel.QD1"]
    qubit_region_list = ["oxide.QD2", "channel.QD2"]

    return dvc, SET_region_list, qubit_region_list

This function starts by generating the Mesh object using the specified mesh file. It then creates an instance of the Device class and sets up the material stack of the device by defining the different regions and assigning them appropriate materials. Next, it applies appropriate boundary conditions to the surfaces representing the gate contacts. The plunger-gate voltages are set according to the function arguments. In contrast, barrier-gate voltages are all set to a value of \(0.5\,\mathrm{V}\). This value of barrier-gate voltage was shown in Tunnel coupling in a double quantum dot in FD-SOI—Part 2: Tuning the barrier gate to lead to minimal tunneling between different regions of the device, allowing the quantum dots to be well-defined and isolated. Finally, the get_double_dot_fdsoi function creates lists identifying the SET region and the qubit region that will later be used when solving the Schrödinger equation before returning the created Device object along with these lists.

Note

In the next section of the practical application (Simulating electrostatics using the linear Poisson solver), we import get_double_dot_fdsoi to construct the FD-SOI device model passed to the linear Poisson Solver to solve the linear Poisson equation. Because the linear Poisson Solver neglects free carriers, the doped "source" and "drain" regions do not contribute any mobile charge to the solution, and therefore their doping has little practical effect in this context. We nevertheless keep the doping definitions here so the same function can be reused to generate a device model for the nonlinear Poisson Solver, which does include free carriers. For an example where the doping becomes relevant, see Tunnel coupling in a double quantum dot in FD-SOI—Part 1: Plunger gate tuning.

2.7. Full code

__copyright__ = "Copyright 2022-2025, Nanoacademic Technologies Inc."

import pathlib
import numpy as np
from qtcad.device import materials as mt
from qtcad.device import constants as ct
from qtcad.device.mesh3d import Mesh
from qtcad.device import Device
from qtcad.device.analysis import plot_slice

# Default values
V_set       = 1.25              # Default SET potential (V)
V_qubit     = 0.75              # Default qubit potential (V)
scaling     = 1e-9              # scaling factor for the mesh

# Visualization parameters
normal = (0., 0., 1.) # the plane of the slice is normal to the z axis
origin = (0., 0., -1. * scaling) # the slice is inside the Si quantum well

def save_slice(device: Device, data: np.ndarray, file_name: str, label: str) -> None:
    """Helper function to save a slice of the device data.

    Args:
        device (Device): The Device object containing the data.
        data (np.ndarray): The data array to be sliced and saved.
        file_name (str): The filename to save the slice plot.
        label (str): The label for the colorbar axis.
    """
    plot_slice(device.mesh, data, normal=normal, origin=origin, cb_axis_label=label,
        path=file_name, show_figure=False)

# Function to create the FD-SOI device
def get_double_dot_fdsoi(mesh_file_name: str="refined_dqdfdsoi.msh",
                        V_set: float=V_set, V_qubit: float=V_qubit) -> Device:
    """Create a Device object for the FD-SOI structure.

    Args:
        V_set (float): Potential applied to the SET gate.
        V_qubit (float): Potential applied to the qubit gate.
        mesh_file_name (str): Filename of the mesh file.

    Returns:
        Device: The constructed Device object.
        list[str]: List of region names associated with the SET.
        list[str]: List of region names associated with the qubit quantum-dot.
    """
    # Create the mesh
    script_dir           = pathlib.Path(__file__).parent.resolve()
    path_mesh            = script_dir / "meshes"
    mesh_file            = path_mesh / mesh_file_name
    mesh                 = Mesh(scaling, mesh_file)

    # Define the device object
    dvc = Device(mesh, conf_carriers='e')
    dvc.set_temperature(0.1)

    # Create the regions
    dvc.new_region("oxide", mt.SiO2)
    dvc.new_region("oxide.QD1", mt.SiO2)
    dvc.new_region("oxide.QD2", mt.SiO2)
    dvc.new_region("channel", mt.Si)
    dvc.new_region("channel.QD1", mt.Si)
    dvc.new_region("channel.QD2", mt.Si)
    dvc.new_region("source", mt.Si, ndoping=1e20*1e6)
    dvc.new_region("drain", mt.Si, ndoping=1e20*1e6)

    # Set up boundary conditions
    Ew = mt.Si.Eg/2 + mt.Si.chi # Midgap
    dvc.new_gate_bnd("barrier_gate_1_bnd", 0.5, Ew)
    dvc.new_gate_bnd("plunger_gate_1_bnd", V_set, Ew)
    dvc.new_gate_bnd("barrier_gate_2_bnd", 0.5, Ew)
    dvc.new_gate_bnd("plunger_gate_2_bnd", V_qubit, Ew)
    dvc.new_gate_bnd("barrier_gate_3_bnd", 0.5, Ew)
    dvc.new_ohmic_bnd("source_bnd")
    dvc.new_ohmic_bnd("drain_bnd")
    dvc.new_frozen_bnd("back_gate_bnd", -0.5, mt.Si, 1e15*1e6, 
        "n", 46*1e-3*ct.e)

    # Create the double quantum dot region
    SET_region_list = ["oxide.QD1", "channel.QD1"]
    qubit_region_list = ["oxide.QD2", "channel.QD2"]

    return dvc, SET_region_list, qubit_region_list