[1]:
%matplotlib inline
from qcodes.dataset.experiment_container import new_experiment
from qcodes.dataset.experiment_container import load_by_id
from qcodes.dataset.plotting import plot_by_id

import nanotune as nt
from nanotune.model.capacitancemodel import CapacitanceModel

Capacitance model for quantum dots

The system of electrostatic gates, dots and reservoirs is represented by a system of conductors connected via resistors and capacitors. Albeit classical and simple, the capacitance model explains and qualitatively reproduces relevant transport features of gate-defined quantum dots.

The capacitance model is defined by a capacitance matrix \(\mathbf{C}\), whose elements \(C_{ij}\) are the capacitances between individual elements \(i\) and \(j\). We distinguish between two different types of elements, the charge and the voltage nodes, representing quantum dots and electrostatic gates respectively. Each node \(i\) is defined by its charge \(Q_{i}\) and electrical potential \(V_{i}\). For simplicity, we write charges and potentials on all nodes of the system in vector notation. We denote charges on charge and voltages nodes by \(\vec{Q_{c}}\) and \(\vec{Q_{v}}\) respectively, and electrical potentials by \(\vec{V}_{c}\) and \(\vec{V}_{v}\). The capacitance model allows to calculate potentials on voltage nodes resulting in the desired number of charges on charge nodes. We consider a system of \(N_{c}\) charge nodes and \(N_{v}\) voltage nodes.

The capacitor connecting node \(j\) and node \(k\) has a capacitance \(C_{jk}\) and stores a charge \(q_{jk}\). The total charge on node \(j\) is the sum of the charges of all capacitors connected to it, \begin{equation} Q_{j} = \sum_{k} q_{jk} = \sum_{k} C_{jk} (V_{j} - V_{k}). \end{equation} Using the vector notation for charges and electrical potentials introduced above, this relation can be expressed using the capacitance matrix, \(\vec{Q} = \mathbf{C} \vec{V}\). Distinguishing between charge and voltage node sub-systems, this relation becomes \begin{equation} \begin{pmatrix} \vec{Q_{c}} \\ \vec{Q_{v}} \end{pmatrix} = \begin{pmatrix} \mathbf{C_{cc}} & \mathbf{C_{cv}} \\ \mathbf{C_{vc}} & \mathbf{C_{vv}} \end{pmatrix} \begin{pmatrix} \vec{V_{c}} \\ \vec{V}_{v} \end{pmatrix}. \end{equation} Diagonal elements of the capacitance matrix, \(C_{jj}\), are total capacitances of each node and carry the opposite sign of the matrix’s off-diagonal elements. The off-diagonal elements of \(\mathbf{\mathbf{C_{cc}}}\) are capacitances between charge nodes, while the off-diagonal elements of \(\mathbf{\mathbf{C_{vv}}}\) are capacitances between voltage nodes. The elements of \(\mathbf{\mathbf{C_{cv}}}\) are capacitances between voltage and charge nodes, and allow to calculate so-called virtual gate coefficients - useful knobs in semiconductor qubit experiments.

Illustration of capacitances between gates and gates and dots:
Each gate voltage \(V_{i}\) will tune the number of charges on each dot. The capacitance of the dots, \(C_{A}\) and \(C_{B}\), are sums of all capacitances connects to \(A\) and \(B\) respectively. Gates located further away will have a smaller capacitive coupling. Most labels of capacitance between gates are omitted for readability.

9400bded06f24af587517c95aefe01a6

Names and layout indices of gates: Six electrostatic gates, three barriers and two plungers, are used to define two, possibly coupled, quantum dots. Barrier gates are primarily used to create potential barriers, while plungers are used to tune electron density and thus the dot’s electrochemical potentials.

7f0f8f3f0c3b4e90bcac93c77bb9f426

Initiate or set database where data should be saved. When initializing a database a new qcodes experiment needs to be created as well.

[2]:
exp_name = 'capacitance_extraction'
sample_name = 'capa_model'
db_name = 'capa_model_test.db'
nt.new_database(db_name, '.')
new_experiment(exp_name, sample_name)
Upgrading database; v0 -> v1: : 0it [00:00, ?it/s]
Upgrading database; v1 -> v2: 100%|█████████████████████████████████████████████████████| 1/1 [00:00<00:00, 504.18it/s]
Upgrading database; v2 -> v3: : 0it [00:00, ?it/s]
Upgrading database; v3 -> v4: : 0it [00:00, ?it/s]
Upgrading database; v4 -> v5: 100%|█████████████████████████████████████████████████████| 1/1 [00:00<00:00, 333.62it/s]
Upgrading database; v5 -> v6: : 0it [00:00, ?it/s]
Upgrading database; v6 -> v7: 100%|█████████████████████████████████████████████████████| 1/1 [00:00<00:00, 142.93it/s]
Upgrading database; v7 -> v8: 100%|█████████████████████████████████████████████████████| 1/1 [00:00<00:00, 333.23it/s]
Upgrading database; v8 -> v9: 100%|█████████████████████████████████████████████████████| 1/1 [00:00<00:00, 250.06it/s]
[2]:
capacitance_extraction#capa_model#1@C:\Workshop\nanotune\docs\examples\capa_model_test.db
-----------------------------------------------------------------------------------------

Initialize an instance of CapacitanceModel with six gates and two dots

[3]:
voltage_nodes = {
    0: 'top_barrier',
    1: 'left_barrier',
    2: 'left_plunger',
    3: 'central_barrier',
    4: 'right_plunger',
    5: 'right_barrier',
}
charge_nodes = {
    0: 'A',
    1: 'B'
}

qdot = CapacitanceModel(
    'qdot',
    charge_nodes=charge_nodes,
    voltage_nodes=voltage_nodes,
    db_name=db_name,
    db_folder='.'
)

Set voltages, define capacitance matrix and calculate ground state dot occupation

[4]:
qdot.V_v([
    -1,  # top_barrier
    -1,  # left_barrier
    -0.5,  # left_plunger
    -1,  # central_barrier
    -0.1,  # right_plunger
    -1,  # right_barrier
])

# off-diagonal entries of C_cc, ie.e inter-dot capacitance
qdot.C_cc([[-2]])
# # capacitances between gates and dots
#           top_b    left_b left_p center right_p  right_b
qdot.C_cv([[-0.6, -0.6, -0.5, -0.5, -0.1, -0.1],   #  A
           [-0.5, -0.3, -0.2, -0.8, -0.5, -0.9]])    #  B

print(qdot.determine_N())
[0.0, 0.0]

Define which dot occupancies to probe and calculate respective voltage ranges of two gates to sweep.

[5]:
N_limits = [(0, 2), (0, 2)]
sweep_ranges = qdot.determine_sweep_voltages([2, 4], N_limits=N_limits)
print(sweep_ranges)
[(2.8260797502049875, 6.304308844864283), (3.8695883841630536, 6.478321143336265)]
[7]:
%%time
dataid = qdot.sweep_voltages(
    [2, 4],
    sweep_ranges,
    n_steps=[40,40],
    target_snr_db=100,
    add_noise=False,
    add_charge_jumps=False,
    normalize=False,
)
plot_by_id(dataid)
Starting experimental run with id: 1.
Wall time: 42.8 s
[7]:
([<AxesSubplot:title={'center':'Run #1, Experiment capacitance_extraction (capa_model)'}, xlabel='voltage node left_plunger (V[2]) (V)', ylabel='voltage node right_plunger (V[4]) (V)'>],
 [<matplotlib.colorbar.Colorbar at 0x162f3134730>])
../_images/examples_capacitance_model_example_double_dot_11_2.png

Sweep one voltage to show Coulomb oscillations

[16]:
qdot.V_v([
    -1,  # top_barrier
    -1,  # left_barrier
    3.2,  # left_plunger
    -1,  # central_barrier
    -0.1,  # right_plunger
    -1,  # right_barrier
])

dataid = qdot.sweep_voltage(
    4,
    sweep_ranges[1],
    n_steps=200,
    target_snr_db=100,
    normalize=False,
   )
plot_by_id(dataid)
Starting experimental run with id: 10.
[16]:
([<AxesSubplot:title={'center':'Run #10, Experiment capacitance_extraction (capa_model)'}, xlabel='voltage node right_plunger (V[4]) (V)', ylabel='Gate R (V)'>],
 [None])
../_images/examples_capacitance_model_example_double_dot_13_2.png